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/
|
||||
packages/
|
||||
.vs/
|
||||
.vsconfig
|
||||
*.dll
|
||||
*.dmp
|
||||
*.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
|
||||
=============
|
||||
|
||||
* Fix bubbles phasing through ceilings.
|
||||
* Fix object camera not clearing at level end.
|
||||
* Fix double breathing sound effect when coming up for air.
|
||||
* Fix twisting hair bug.
|
||||
* Fix double breath sound effect when coming up for air.
|
||||
* Fix flickering hair.
|
||||
* Fix harpoon gun triggering water and dry sounds when shooting and reholstering.
|
||||
* Fix Z-fighting in inventory rendering.
|
||||
* Fix transparent objects not displaying correctly in the Inventory.
|
||||
* 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 going through trapdoor/bridge while climbing up a climbable wall.
|
||||
* Fix TR3 Sophia's charge ring drawing below floor.
|
||||
* Fix TR5 imp collision handling and animations.
|
||||
- OCB 1 - Climbs up to Lara when triggered.
|
||||
- OCB 2 - Starts of playfully rolling on the floor when triggered.
|
||||
- OCB 3 - Will throw stones at Lara.
|
||||
- Imp is also scared of Lara if she has a lit torch in her hand.
|
||||
* Fix TR5 imp collision handling and animations:
|
||||
- OCB 1: Climbs up to player when triggered.
|
||||
- OCB 2: Starts rolling on the floor when triggered.
|
||||
- OCB 3: Will throw stones at player.
|
||||
- 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
|
||||
* Fix and improve wraith tails.
|
||||
* Add dedicated WRAITH_TRAP object with enhanced effects.
|
||||
|
@ -24,22 +64,23 @@ Version 1.0.8
|
|||
* Add TR1 slamming doors.
|
||||
* Add TR3 mutant wasp (AI_MODIFY object won't allow it to land, the wasp will always fly).
|
||||
* 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.
|
||||
- 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 water wakes for vehicles.
|
||||
* Allow dynamic segment count of hair object.
|
||||
* Restored light effect nullmeshes (color, electrical, pulse and strobe):
|
||||
- Select the color the light should emit as object tint in OCB menu in Tomb editor.
|
||||
* Restored light effect nullmeshes (color, electrical, pulse, and strobe):
|
||||
- Select the light color as object tint in the OCB menu in Tomb Editor.
|
||||
- ELECTRICAL_LIGHT:
|
||||
- OCB 1: Displays mesh of object.
|
||||
- OCB -1: Hides mesh of object (used for a neon light effect)
|
||||
|
||||
- Can have multiple meshes. Add mesh number to OCB to be renderd with the light.
|
||||
- OCB + (mesh number): Light behaves like a neon light.
|
||||
- OCB – (mesh number): Light flickers.
|
||||
* Restored inventory compass.
|
||||
* Allow dynamic segment count for hair object.
|
||||
|
||||
Lua API changes:
|
||||
* Add new function Misc::IsSoundPlaying()
|
||||
* Add function Misc::IsSoundPlaying()
|
||||
* Add function DisplayString::SetFlags()
|
||||
|
||||
Version 1.0.7
|
||||
=============
|
||||
|
|
|
@ -12,7 +12,7 @@ new_type("luautil", "5 Lua utility modules", true)
|
|||
|
||||
not_luadoc = true
|
||||
|
||||
local version = "1.0.8"
|
||||
local version = "1.0.9"
|
||||
project = "TombEngine"
|
||||
title = "TombEngine " .. version .. " Lua API"
|
||||
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="summary">Get the position of the string.</td>
|
||||
</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>
|
||||
|
||||
<br/>
|
||||
|
@ -250,7 +254,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
|||
<h3>Returns:</h3>
|
||||
<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
|
||||
</ol>
|
||||
|
||||
|
@ -272,7 +276,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
|||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<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
|
||||
</li>
|
||||
</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>
|
||||
</dl>
|
||||
|
||||
|
@ -341,7 +377,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
|||
</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-03-31 20:44:31 </i>
|
||||
<i style="float:right;">Last updated 2023-04-11 21:28:36 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</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>
|
||||
<returns>
|
||||
<return>
|
||||
<type>String</type>
|
||||
<type>string</type>
|
||||
<description>a string</description>
|
||||
</return>
|
||||
</returns>
|
||||
|
@ -3842,7 +3842,7 @@ __Default: empty__</description>
|
|||
<parameters>
|
||||
<parameter>
|
||||
<name>string</name>
|
||||
<type>String</type>
|
||||
<type>string</type>
|
||||
<description>the new key for the display string</description>
|
||||
</parameter>
|
||||
</parameters>
|
||||
|
@ -3886,6 +3886,20 @@ __Default: empty__</description>
|
|||
</returns>
|
||||
</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>
|
||||
<module>Strings</module>
|
||||
<name>ShowString</name>
|
||||
|
|
|
@ -277,7 +277,7 @@ 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
|
||||
-- @function myTimer:GetRemainingTime
|
||||
-- @function myTimer:GetTotalTime
|
||||
-- @treturn float the timer's total time
|
||||
GetTotalTime = function(t)
|
||||
return LevelVars.Engine.Timer.timers[t.name].totalTime
|
||||
|
|
|
@ -347,8 +347,8 @@ namespace TEN::Gui
|
|||
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||
lara->Control.Weapon.GunType == LaraWeaponType::Revolver)
|
||||
{
|
||||
UndrawPistolMeshRight(item, LaraWeaponType::Revolver);
|
||||
DrawPistolMeshes(item, LaraWeaponType::Revolver);
|
||||
UndrawPistolMesh(*item, LaraWeaponType::Revolver, true);
|
||||
DrawPistolMeshes(*item, LaraWeaponType::Revolver);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,8 +370,8 @@ namespace TEN::Gui
|
|||
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||
lara->Control.Weapon.GunType == LaraWeaponType::Crossbow)
|
||||
{
|
||||
UndrawShotgunMeshes(item, LaraWeaponType::Crossbow);
|
||||
DrawShotgunMeshes(item, LaraWeaponType::Crossbow);
|
||||
UndrawShotgunMeshes(*item, LaraWeaponType::Crossbow);
|
||||
DrawShotgunMeshes(*item, LaraWeaponType::Crossbow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,8 +393,8 @@ namespace TEN::Gui
|
|||
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||
lara->Control.Weapon.GunType == LaraWeaponType::HK)
|
||||
{
|
||||
UndrawShotgunMeshes(item, LaraWeaponType::HK);
|
||||
DrawShotgunMeshes(item, LaraWeaponType::HK);
|
||||
UndrawShotgunMeshes(*item, LaraWeaponType::HK);
|
||||
DrawShotgunMeshes(*item, LaraWeaponType::HK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,21 +11,21 @@ namespace TEN::Hud
|
|||
{
|
||||
HudController g_Hud = {};
|
||||
|
||||
void HudController::Update(ItemInfo& item)
|
||||
void HudController::Update(const ItemInfo& item)
|
||||
{
|
||||
this->PickupSummary.Update();
|
||||
this->StatusBars.Update(item);
|
||||
PickupSummary.Update();
|
||||
StatusBars.Update(item);
|
||||
}
|
||||
|
||||
void HudController::Draw(ItemInfo& item) const
|
||||
void HudController::Draw(const ItemInfo& item) const
|
||||
{
|
||||
this->PickupSummary.Draw();
|
||||
this->StatusBars.Draw(item);
|
||||
PickupSummary.Draw();
|
||||
StatusBars.Draw(item);
|
||||
}
|
||||
|
||||
void HudController::Clear()
|
||||
{
|
||||
this->PickupSummary.Clear();
|
||||
this->StatusBars.Clear();
|
||||
PickupSummary.Clear();
|
||||
StatusBars.Clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@ namespace TEN::Hud
|
|||
class HudController
|
||||
{
|
||||
public:
|
||||
// Components
|
||||
// Members
|
||||
StatusBarsController StatusBars = {};
|
||||
PickupSummaryController PickupSummary = {};
|
||||
|
||||
// Utilities
|
||||
void Update(ItemInfo& item);
|
||||
void Draw(ItemInfo& item) const;
|
||||
void Update(const ItemInfo& item);
|
||||
void Draw(const ItemInfo& item) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
|
|
@ -12,22 +12,50 @@
|
|||
|
||||
using namespace TEN::Renderer;
|
||||
|
||||
extern TEN::Renderer::RendererHudBar* g_AirBar;
|
||||
extern TEN::Renderer::RendererHudBar* g_ExposureBar;
|
||||
extern TEN::Renderer::RendererHudBar* g_HealthBar;
|
||||
extern TEN::Renderer::RendererHudBar* g_StaminaBar;
|
||||
extern RendererHudBar* g_AirBar;
|
||||
extern RendererHudBar* g_ExposureBar;
|
||||
extern RendererHudBar* g_HealthBar;
|
||||
extern RendererHudBar* g_StaminaBar;
|
||||
|
||||
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)
|
||||
{
|
||||
const auto& player = GetLaraInfo(item);
|
||||
|
||||
// Initialize bar values.
|
||||
InitializeStatusBar(AirBar, player.Status.Air, LARA_AIR_MAX);
|
||||
InitializeStatusBar(ExposureBar, player.Status.Exposure, LARA_EXPOSURE_MAX);
|
||||
InitializeStatusBar(HealthBar, item.HitPoints, LARA_HEALTH_MAX);
|
||||
InitializeStatusBar(StaminaBar, player.Status.Stamina, LARA_STAMINA_MAX);
|
||||
AirBar.Initialize(player.Status.Air / LARA_AIR_MAX);
|
||||
ExposureBar.Initialize(player.Status.Exposure / LARA_EXPOSURE_MAX);
|
||||
HealthBar.Initialize(item.HitPoints / LARA_HEALTH_MAX);
|
||||
StaminaBar.Initialize(player.Status.Stamina / LARA_STAMINA_MAX);
|
||||
}
|
||||
|
||||
void StatusBarsController::Update(const ItemInfo& item)
|
||||
|
@ -66,52 +94,26 @@ namespace TEN::Hud
|
|||
*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)
|
||||
{
|
||||
const auto& player = GetLaraInfo(item);
|
||||
|
||||
// Update generic data.
|
||||
UpdateStatusBar(AirBar, player.Status.Air, LARA_AIR_MAX);
|
||||
AirBar.Update(player.Status.Air / LARA_AIR_MAX);
|
||||
|
||||
// Update life.
|
||||
if (AirBar.Value != AirBar.TargetValue ||
|
||||
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.
|
||||
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)
|
||||
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);
|
||||
|
||||
// Update generic data.
|
||||
UpdateStatusBar(ExposureBar, player.Status.Exposure, LARA_EXPOSURE_MAX);
|
||||
ExposureBar.Update(player.Status.Exposure / LARA_EXPOSURE_MAX);
|
||||
|
||||
// Update life.
|
||||
if (ExposureBar.Value != ExposureBar.TargetValue ||
|
||||
(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);
|
||||
|
||||
// Update generic data.
|
||||
UpdateStatusBar(HealthBar, item.HitPoints, LARA_HEALTH_MAX);
|
||||
HealthBar.Update(item.HitPoints / LARA_HEALTH_MAX);
|
||||
|
||||
// Update life.
|
||||
if (HealthBar.Value != HealthBar.TargetValue ||
|
||||
|
@ -145,7 +147,7 @@ namespace TEN::Hud
|
|||
(player.Control.HandStatus == HandStatus::WeaponReady &&
|
||||
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.
|
||||
|
@ -153,7 +155,7 @@ namespace TEN::Hud
|
|||
item.HitPoints > LARA_HEALTH_CRITICAL && player.Status.Poison == 0 &&
|
||||
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);
|
||||
|
||||
// Update generic data.
|
||||
UpdateStatusBar(StaminaBar, player.Status.Stamina, LARA_STAMINA_MAX);
|
||||
StaminaBar.Update(player.Status.Stamina / LARA_STAMINA_MAX);
|
||||
|
||||
// Update life.
|
||||
if (StaminaBar.Value != StaminaBar.TargetValue ||
|
||||
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;
|
||||
struct ItemInfo;
|
||||
namespace TEN::Renderer { struct RendererHudBar; }
|
||||
|
||||
namespace TEN::Renderer
|
||||
{
|
||||
struct RendererHudBar;
|
||||
}
|
||||
using namespace TEN::Renderer;
|
||||
|
||||
namespace TEN::Hud
|
||||
{
|
||||
struct StatusBar
|
||||
{
|
||||
static constexpr auto LIFE_MAX = 0.75f;
|
||||
|
||||
float Value = 0.0f;
|
||||
float TargetValue = 0.0f;
|
||||
float Life = 0.0f;
|
||||
float Opacity = 0.0f; // TODO: Opacity in renderer.
|
||||
|
||||
void Initialize(float value);
|
||||
void Update(float value);
|
||||
};
|
||||
|
||||
class StatusBarsController
|
||||
{
|
||||
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
|
||||
StatusBar AirBar = {};
|
||||
StatusBar ExposureBar = {};
|
||||
|
@ -42,18 +40,14 @@ namespace TEN::Hud
|
|||
void Clear();
|
||||
|
||||
private:
|
||||
// Initializer helpers
|
||||
void InitializeStatusBar(StatusBar& bar, float statusValue, float statusValueMax);
|
||||
|
||||
// Update helpers
|
||||
void UpdateStatusBar(StatusBar& bar, float statusValue, float statusValueMax);
|
||||
void UpdateAirBar(const ItemInfo& item);
|
||||
void UpdateExposureBar(const ItemInfo& item);
|
||||
void UpdateHealthBar(const ItemInfo& item);
|
||||
void UpdateStaminaBar(const ItemInfo& item);
|
||||
|
||||
// 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 DrawExposureBar() const;
|
||||
void DrawHealthBar(bool isPoisoned) const;
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
using namespace TEN::Control::Volumes;
|
||||
using namespace TEN::Effects::Hair;
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Input;
|
||||
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_crawl_turn_180,//172
|
||||
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] =
|
||||
|
@ -410,6 +426,22 @@ std::function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1]
|
|||
lara_col_crouch_turn_180,//171
|
||||
lara_col_crawl_turn_180,//172
|
||||
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)
|
||||
|
@ -479,12 +511,12 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
heightFromWater = item->Pose.Position.y - waterHeight;
|
||||
else
|
||||
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);
|
||||
|
||||
if (lara->Vehicle == NO_ITEM && lara->ExtraAnim == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM && lara->ExtraAnim == NO_ITEM)
|
||||
{
|
||||
switch (lara->Control.WaterStatus)
|
||||
{
|
||||
|
@ -534,7 +566,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
item->Pose.Orientation.x = -ANGLE(45.0f);
|
||||
}
|
||||
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
Splash(item);
|
||||
}
|
||||
}
|
||||
|
@ -591,8 +623,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
if (waterDepth == NO_HEIGHT || abs(heightFromWater) >= CLICK(1))
|
||||
{
|
||||
SetAnimation(item, LA_FALL_START);
|
||||
ResetLaraLean(item);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.IsAirborne = true;
|
||||
item->Animation.Velocity.z = item->Animation.Velocity.y;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
|
@ -601,8 +633,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
else
|
||||
{
|
||||
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
||||
ResetLaraLean(item);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y = waterHeight;
|
||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||
|
@ -614,8 +646,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
else
|
||||
{
|
||||
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
||||
ResetLaraLean(item);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y = waterHeight + 1;
|
||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||
|
@ -641,8 +673,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||
}
|
||||
|
||||
ResetLaraLean(item);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
|
@ -656,8 +688,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
if (heightFromWater > SWIM_DEPTH && !isSwamp)
|
||||
{
|
||||
SetAnimation(item, LA_ONWATER_IDLE);
|
||||
ResetLaraLean(item);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.IsAirborne = false;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y += 1 - heightFromWater;
|
||||
|
@ -702,7 +734,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
case WaterStatus::Dry:
|
||||
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)
|
||||
{
|
||||
|
@ -717,7 +749,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
else if (lara->Status.Air < LARA_AIR_MAX && item->HitPoints >= 0)
|
||||
{
|
||||
// HACK: Special case for UPV.
|
||||
if (lara->Vehicle == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
{
|
||||
lara->Status.Air += 10;
|
||||
if (lara->Status.Air > LARA_AIR_MAX)
|
||||
|
@ -730,23 +762,23 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
if (lara->Control.WaterStatus == WaterStatus::Dry)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
auto pointColl = GetCollision(item, 0, 0, CLICK(1));
|
||||
isCold = isCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber);
|
||||
}
|
||||
}
|
||||
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure--;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
isCold = isCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber);
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure--;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -853,6 +885,7 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
|
|||
coll->Setup.EnableSpasm = true;
|
||||
|
||||
coll->Setup.OldPosition = item->Pose.Position;
|
||||
coll->Setup.PrevAnimObjectID = item->Animation.AnimObjectID;
|
||||
coll->Setup.OldAnimNumber = item->Animation.AnimNumber;
|
||||
coll->Setup.OldFrameNumber = item->Animation.FrameNumber;
|
||||
coll->Setup.OldState = item->Animation.ActiveState;
|
||||
|
@ -889,12 +922,12 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
|
|||
DoObjectCollision(item, coll);
|
||||
|
||||
// Handle Lara collision.
|
||||
if (lara->Vehicle == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
||||
}
|
||||
|
||||
// Handle weapons.
|
||||
HandleWeapon(item);
|
||||
HandleWeapon(*item);
|
||||
|
||||
// Handle breath.
|
||||
LaraBreath(item);
|
||||
|
@ -957,9 +990,9 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
// Reset lean.
|
||||
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);
|
||||
|
||||
AnimateItem(item);
|
||||
|
@ -967,12 +1000,12 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
DoObjectCollision(item, coll);
|
||||
|
||||
if (lara->Vehicle == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
||||
|
||||
UpdateLaraRoom(item, LARA_RADIUS);
|
||||
|
||||
HandleWeapon(item);
|
||||
HandleWeapon(*item);
|
||||
|
||||
ProcessSectorFlags(item);
|
||||
TestTriggers(item, false);
|
||||
|
@ -1026,7 +1059,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
|
|||
UpdateLaraSubsuitAngles(item);
|
||||
|
||||
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))
|
||||
item->Pose.Orientation.x = -ANGLE(85.0f);
|
||||
|
@ -1048,7 +1081,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
|
|||
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);
|
||||
|
||||
AnimateItem(item);
|
||||
|
@ -1056,12 +1089,12 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* 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);
|
||||
|
||||
UpdateLaraRoom(item, 0);
|
||||
|
||||
HandleWeapon(item);
|
||||
HandleWeapon(*item);
|
||||
|
||||
ProcessSectorFlags(item);
|
||||
TestTriggers(item, false);
|
||||
|
@ -1082,10 +1115,10 @@ void LaraCheat(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
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);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
lara->Control.WaterStatus = WaterStatus::Underwater;
|
||||
}
|
||||
else
|
||||
|
@ -1093,11 +1126,11 @@ void LaraCheat(ItemInfo* item, CollisionInfo* coll)
|
|||
SetAnimation(item, LA_STAND_SOLID);
|
||||
item->Pose.Orientation.x = 0;
|
||||
item->Pose.Orientation.z = 0;
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
lara->Control.WaterStatus = WaterStatus::Dry;
|
||||
}
|
||||
|
||||
InitialiseLaraMeshes(item);
|
||||
InitializeLaraMeshes(item);
|
||||
item->HitPoints = LARA_HEALTH_MAX;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
#include "Game/Lara/lara_monkey.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/pickup/pickup.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||
|
||||
using namespace TEN::Input;
|
||||
|
@ -73,7 +73,7 @@ void lara_as_controlled(ItemInfo* item, CollisionInfo* coll)
|
|||
coll->Setup.EnableSpasm = false;
|
||||
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;
|
||||
|
||||
|
@ -103,8 +103,8 @@ void lara_as_vault(ItemInfo* item, CollisionInfo* coll)
|
|||
coll->Setup.EnableObjectPush = false;
|
||||
coll->Setup.EnableSpasm = false;
|
||||
|
||||
EaseOutLaraHeight(item, lara->ProjectedFloorHeight - item->Pose.Position.y);
|
||||
item->Pose.Orientation.Lerp(lara->TargetOrientation, 0.4f);
|
||||
EaseOutLaraHeight(item, lara->Context.ProjectedFloorHeight - item->Pose.Position.y);
|
||||
item->Pose.Orientation.Lerp(lara->Context.TargetOrientation, 0.4f);
|
||||
|
||||
item->Animation.TargetState = LS_IDLE;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ void lara_as_auto_jump(ItemInfo* item, CollisionInfo* coll)
|
|||
coll->Setup.EnableObjectPush = 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))
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -349,13 +349,13 @@ void lara_col_run_forward(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
if (LaraDeflectEdge(item, coll))
|
||||
{
|
||||
ResetLaraLean(item);
|
||||
ResetPlayerLean(item);
|
||||
|
||||
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
||||
coll->HitTallObject)
|
||||
{
|
||||
item->Animation.TargetState = LS_SPLAT;
|
||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
||||
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||
{
|
||||
Rumble(0.4f, 0.15f);
|
||||
|
||||
|
@ -365,7 +365,7 @@ void lara_col_run_forward(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
|
@ -1880,7 +1880,7 @@ void lara_col_step_right(ItemInfo* item, CollisionInfo* coll)
|
|||
if (LaraDeflectEdge(item, coll))
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -1974,7 +1974,7 @@ void lara_col_step_left(ItemInfo* item, CollisionInfo* coll)
|
|||
if (LaraDeflectEdge(item, coll))
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -2227,10 +2227,10 @@ void lara_col_wade_forward(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
if (LaraDeflectEdge(item, coll))
|
||||
{
|
||||
ResetLaraLean(item);
|
||||
ResetPlayerLean(item);
|
||||
|
||||
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;
|
||||
return;
|
||||
|
@ -2355,13 +2355,13 @@ void lara_col_sprint(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
if (LaraDeflectEdge(item, coll))
|
||||
{
|
||||
ResetLaraLean(item);
|
||||
ResetPlayerLean(item);
|
||||
|
||||
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
||||
coll->HitTallObject)
|
||||
{
|
||||
item->Animation.TargetState = LS_SPLAT;
|
||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
||||
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||
{
|
||||
Rumble(0.5f, 0.15f);
|
||||
|
||||
|
@ -2371,7 +2371,7 @@ void lara_col_sprint(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Gui;
|
||||
using namespace TEN::Input;
|
||||
|
@ -62,7 +62,7 @@ void LaraCheatyBits(ItemInfo* item)
|
|||
static bool dbFlyCheat = true;
|
||||
if (KeyMap[OIS::KeyCode::KC_O] && dbFlyCheat)
|
||||
{
|
||||
if (lara->Vehicle == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
{
|
||||
LaraCheatGetStuff(item);
|
||||
DelsGiveLaraItemsCheat(item);
|
||||
|
@ -77,7 +77,7 @@ void LaraCheatyBits(ItemInfo* item)
|
|||
item->Pose.Orientation.x = ANGLE(30.0f);
|
||||
item->HitPoints = LARA_HEALTH_MAX;
|
||||
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
lara->Control.WaterStatus = WaterStatus::FlyCheat;
|
||||
lara->Control.Count.Death = 0;
|
||||
lara->Status.Air = LARA_AIR_MAX;
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_overhang.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
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;
|
||||
|
||||
// -----------------------------
|
||||
// LADDER CLIMB
|
||||
// WALL CLIMB
|
||||
// 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)
|
||||
{
|
||||
if (LaraCheckForLetGo(item, coll) || item->Animation.AnimNumber != LA_LADDER_DOWN)
|
||||
if (LaraCheckForLetGo(item, coll) || !TestAnimNumber(*item, LA_LADDER_DOWN))
|
||||
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;
|
||||
|
||||
switch (frame)
|
||||
|
@ -128,9 +128,9 @@ void lara_as_climb_down(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 resultRight, resultLeft;
|
||||
int shiftRight, shiftLeft;
|
||||
|
@ -304,6 +304,10 @@ void lara_col_climb_idle(ItemInfo* item, CollisionInfo* coll)
|
|||
return;
|
||||
}
|
||||
|
||||
// Added check to avoid climbing through bridges.
|
||||
if (resultRight == 0 && resultLeft == 0)
|
||||
return;
|
||||
|
||||
if (resultRight >= 0 && resultLeft >= 0)
|
||||
{
|
||||
yShift = shiftLeft;
|
||||
|
@ -321,7 +325,7 @@ void lara_col_climb_idle(ItemInfo* item, CollisionInfo* coll)
|
|||
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));
|
||||
auto probe = GetCollision(item, 0, 0, -(coll->Setup.Height + CLICK(0.5f)));
|
||||
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)
|
||||
Camera.targetAngle = -ANGLE(60.0f);
|
||||
|
||||
if (item->Animation.AnimNumber == LA_LADDER_DISMOUNT_RIGHT_START)
|
||||
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])
|
||||
{
|
||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->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.Position.x = item->Pose.Position.x = x;
|
||||
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||
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);
|
||||
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])
|
||||
{
|
||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->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.Position.x = item->Pose.Position.x = x;
|
||||
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||
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);
|
||||
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])
|
||||
{
|
||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->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.Position.x = item->Pose.Position.x = x;
|
||||
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||
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);
|
||||
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])
|
||||
{
|
||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->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.Position.x = item->Pose.Position.x = x;
|
||||
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||
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);
|
||||
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 y = item->Pose.Position.y - 768;
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
*shift = 0;
|
||||
|
||||
short roomNumber = item->RoomNumber;
|
||||
FloorInfo* floor = GetFloor(x, y, z, &roomNumber);
|
||||
int ceiling = CLICK(1) - y + GetCeiling(floor, x, y, z);
|
||||
// Test center.
|
||||
auto pointColl = GetCollision(item);
|
||||
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);
|
||||
int height = GetFloorHeight(floor, x + xFront, y, z + zFront);
|
||||
pointColl = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber);
|
||||
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)
|
||||
{
|
||||
|
@ -934,7 +914,7 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
|||
}
|
||||
else
|
||||
{
|
||||
height -= y;
|
||||
height -= probePos.y;
|
||||
*ledge = height;
|
||||
}
|
||||
|
||||
|
@ -955,12 +935,13 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
|||
if (height > 0 && height > *shift)
|
||||
*shift = height;
|
||||
|
||||
roomNumber = item->RoomNumber;
|
||||
GetFloor(x, y + CLICK(2), z, &roomNumber);
|
||||
floor = GetFloor(x + xFront, y + CLICK(2), z + zFront, &roomNumber);
|
||||
ceiling = GetCeiling(floor, x + xFront, y + CLICK(2), z + zFront) - y;
|
||||
pointColl = GetCollision(probePos.x, probePos.y + CLICK(2), probePos.z, item->RoomNumber);
|
||||
pointColl = GetCollision(probePos.x + probeOffset.x, probePos.y + CLICK(2), probePos.z + probeOffset.z, pointColl.RoomNumber);
|
||||
|
||||
ceiling = pointColl.Position.Ceiling - probePos.y;
|
||||
if (ceiling <= height)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
if (ceiling >= CLICK(2))
|
||||
return 1;
|
||||
else
|
||||
|
@ -968,13 +949,14 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
|||
}
|
||||
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 ((height - ceiling) <= LARA_HEIGHT)
|
||||
{
|
||||
if ((height - ceiling) < CLICK(2))
|
||||
return 0;
|
||||
|
||||
*shift = height;
|
||||
return -2;
|
||||
}
|
||||
|
@ -985,7 +967,9 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
return false;
|
||||
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
|
||||
SetAnimation(item, LA_FALL_START);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ static ClimbDirectionFlags LeftExtRightIntTab[4] =
|
|||
};
|
||||
|
||||
// -----------------------------
|
||||
// LADDER CLIMB
|
||||
// WALL CLIMB
|
||||
// Control & Collision Functions
|
||||
// -----------------------------
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_swim.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Objects/Sink.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "ScriptInterfaceLevel.h"
|
||||
|
||||
|
@ -239,9 +239,10 @@ void LaraCollideStop(ItemInfo* item, CollisionInfo* coll)
|
|||
case LS_TURN_LEFT_SLOW:
|
||||
case LS_TURN_RIGHT_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.FrameNumber = coll->Setup.OldFrameNumber;
|
||||
item->Animation.ActiveState = coll->Setup.OldState;
|
||||
|
||||
if (TrInput & IN_LEFT)
|
||||
{
|
||||
|
@ -288,9 +289,10 @@ void LaraCollideStopCrawl(ItemInfo* item, CollisionInfo* coll)
|
|||
case LS_CRAWL_IDLE:
|
||||
case LS_CRAWL_TURN_LEFT:
|
||||
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.FrameNumber = coll->Setup.OldFrameNumber;
|
||||
item->Animation.ActiveState = coll->Setup.OldState;
|
||||
|
||||
if (TrInput & IN_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)
|
||||
{
|
||||
item->Animation.AnimNumber = LA_CRAWL_IDLE;
|
||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
||||
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -323,9 +325,10 @@ void LaraCollideStopMonkey(ItemInfo* item, CollisionInfo* coll)
|
|||
case LS_MONKEY_IDLE:
|
||||
case LS_MONKEY_TURN_LEFT:
|
||||
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.FrameNumber = coll->Setup.OldFrameNumber;
|
||||
item->Animation.ActiveState = coll->Setup.OldState;
|
||||
|
||||
if (TrInput & IN_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)
|
||||
{
|
||||
item->Animation.AnimNumber = LA_MONKEY_IDLE;
|
||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
||||
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -621,13 +624,13 @@ void LaraWaterCurrent(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
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;
|
||||
lara->WaterCurrentPull.x += ((sink.Strength * SECTOR(1) * phd_sin(headingAngle)) - lara->WaterCurrentPull.x) / 16;
|
||||
lara->WaterCurrentPull.z += ((sink.Strength * SECTOR(1) * phd_cos(headingAngle)) - lara->WaterCurrentPull.z) / 16;
|
||||
lara->Context.WaterCurrentPull.x += ((sink.Strength * SECTOR(1) * phd_sin(headingAngle)) - lara->Context.WaterCurrentPull.x) / 16;
|
||||
lara->Context.WaterCurrentPull.z += ((sink.Strength * SECTOR(1) * phd_cos(headingAngle)) - lara->Context.WaterCurrentPull.z) / 16;
|
||||
|
||||
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;
|
||||
|
||||
if (abs(lara->WaterCurrentPull.x) <= 16)
|
||||
shift = (abs(lara->WaterCurrentPull.x) > 8) + 2;
|
||||
if (abs(lara->Context.WaterCurrentPull.x) <= 16)
|
||||
shift = (abs(lara->Context.WaterCurrentPull.x) > 8) + 2;
|
||||
else
|
||||
shift = 4;
|
||||
lara->WaterCurrentPull.x -= lara->WaterCurrentPull.x >> shift;
|
||||
lara->Context.WaterCurrentPull.x -= lara->Context.WaterCurrentPull.x >> shift;
|
||||
|
||||
if (abs(lara->WaterCurrentPull.x) < 4)
|
||||
lara->WaterCurrentPull.x = 0;
|
||||
if (abs(lara->Context.WaterCurrentPull.x) < 4)
|
||||
lara->Context.WaterCurrentPull.x = 0;
|
||||
|
||||
if (abs(lara->WaterCurrentPull.z) <= 16)
|
||||
shift = (abs(lara->WaterCurrentPull.z) > 8) + 2;
|
||||
if (abs(lara->Context.WaterCurrentPull.z) <= 16)
|
||||
shift = (abs(lara->Context.WaterCurrentPull.z) > 8) + 2;
|
||||
else
|
||||
shift = 4;
|
||||
lara->WaterCurrentPull.z -= lara->WaterCurrentPull.z >> shift;
|
||||
lara->Context.WaterCurrentPull.z -= lara->Context.WaterCurrentPull.z >> shift;
|
||||
|
||||
if (abs(lara->WaterCurrentPull.z) < 4)
|
||||
lara->WaterCurrentPull.z = 0;
|
||||
if (abs(lara->Context.WaterCurrentPull.z) < 4)
|
||||
lara->Context.WaterCurrentPull.z = 0;
|
||||
|
||||
if (!lara->WaterCurrentPull.x && !lara->WaterCurrentPull.z)
|
||||
if (!lara->Context.WaterCurrentPull.x && !lara->Context.WaterCurrentPull.z)
|
||||
return;
|
||||
}
|
||||
|
||||
item->Pose.Position.x += lara->WaterCurrentPull.x / 256;
|
||||
item->Pose.Position.z += lara->WaterCurrentPull.z / 256;
|
||||
lara->WaterCurrentActive = 0;
|
||||
item->Pose.Position.x += lara->Context.WaterCurrentPull.x / 256;
|
||||
item->Pose.Position.z += lara->Context.WaterCurrentPull.z / 256;
|
||||
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.Height = LARA_HEIGHT_CRAWL;
|
||||
|
|
|
@ -434,7 +434,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
item->Animation.TargetState = crawlVaultResult.TargetState;
|
||||
lara->Control.TurnRate = 0;
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
return;
|
||||
}
|
||||
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.targetDistance = SECTOR(1);
|
||||
|
||||
ResetLaraLean(item, 6.0f);
|
||||
ResetPlayerLean(item, 1 / 6.0f);
|
||||
|
||||
if (item->Animation.AnimNumber == LA_CRAWL_TO_HANG_END)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "Game/Lara/lara_two_guns.h"
|
||||
#include "Game/misc.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Generic/Object/burning_torch.h"
|
||||
#include "Objects/Generic/Object/objects.h"
|
||||
|
@ -28,14 +29,15 @@
|
|||
#include "Specific/configuration.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Input;
|
||||
using namespace TEN::Math;
|
||||
|
||||
ItemInfo* LastTargets[MAX_TARGETS];
|
||||
ItemInfo* TargetList[MAX_TARGETS];
|
||||
constexpr auto TARGET_COUNT_MAX = 8;
|
||||
|
||||
std::array<ItemInfo*, TARGET_COUNT_MAX> LastTargets = {};
|
||||
std::array<ItemInfo*, TARGET_COUNT_MAX> TargetList = {};
|
||||
|
||||
int FlashGrenadeAftershockTimer = 0;
|
||||
|
||||
|
@ -88,7 +90,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
650,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
1,
|
||||
9,
|
||||
3,
|
||||
|
@ -105,7 +107,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(4.0f),
|
||||
650,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
21,
|
||||
16,
|
||||
3,
|
||||
|
@ -122,7 +124,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
650,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
1,
|
||||
3,
|
||||
3,
|
||||
|
@ -139,7 +141,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
0,
|
||||
500,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
3,
|
||||
9,
|
||||
3,
|
||||
|
@ -156,7 +158,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(4.0f),
|
||||
500,
|
||||
SECTOR(12),
|
||||
BLOCK(12),
|
||||
4,
|
||||
0,
|
||||
3,
|
||||
|
@ -173,7 +175,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
500,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
|
@ -199,7 +201,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
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)),
|
||||
|
@ -207,7 +209,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
400,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
3,
|
||||
0,
|
||||
2,
|
||||
|
@ -224,7 +226,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
500,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
20,
|
||||
0,
|
||||
2,
|
||||
|
@ -241,7 +243,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
500,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
6,
|
||||
0,
|
||||
2,
|
||||
|
@ -258,7 +260,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
500,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
30,
|
||||
0,
|
||||
2,
|
||||
|
@ -275,39 +277,39 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
ANGLE(10.0f),
|
||||
ANGLE(8.0f),
|
||||
400,
|
||||
SECTOR(8),
|
||||
BLOCK(8),
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
SFX_TR4_UZI_FIRE,
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
void InitialiseNewWeapon(ItemInfo* laraItem)
|
||||
void InitializeNewWeapon(ItemInfo& laraItem)
|
||||
{
|
||||
auto& lara = *GetLaraInfo(laraItem);
|
||||
auto& player = *GetLaraInfo(&laraItem);
|
||||
|
||||
lara.LeftArm.FrameNumber = 0;
|
||||
lara.RightArm.FrameNumber = 0;
|
||||
lara.LeftArm.Orientation = EulerAngles::Zero;
|
||||
lara.RightArm.Orientation = EulerAngles::Zero;
|
||||
lara.TargetEntity = nullptr;
|
||||
lara.LeftArm.Locked = false;
|
||||
lara.RightArm.Locked = false;
|
||||
lara.LeftArm.GunFlash = 0;
|
||||
lara.RightArm.GunFlash = 0;
|
||||
player.TargetEntity = nullptr;
|
||||
player.LeftArm.FrameNumber =
|
||||
player.RightArm.FrameNumber = 0;
|
||||
player.LeftArm.Orientation =
|
||||
player.RightArm.Orientation = EulerAngles::Zero;
|
||||
player.LeftArm.Locked =
|
||||
player.RightArm.Locked = false;
|
||||
player.LeftArm.GunFlash =
|
||||
player.RightArm.GunFlash = 0;
|
||||
|
||||
switch (lara.Control.Weapon.GunType)
|
||||
switch (player.Control.Weapon.GunType)
|
||||
{
|
||||
case LaraWeaponType::Pistol:
|
||||
case LaraWeaponType::Uzi:
|
||||
lara.RightArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||
lara.LeftArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||
player.RightArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||
player.LeftArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||
|
||||
if (lara.Control.HandStatus != HandStatus::Free)
|
||||
DrawPistolMeshes(laraItem, lara.Control.Weapon.GunType);
|
||||
if (player.Control.HandStatus != HandStatus::Free)
|
||||
DrawPistolMeshes(laraItem, player.Control.Weapon.GunType);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -317,26 +319,26 @@ void InitialiseNewWeapon(ItemInfo* laraItem)
|
|||
case LaraWeaponType::GrenadeLauncher:
|
||||
case LaraWeaponType::HarpoonGun:
|
||||
case LaraWeaponType::RocketLauncher:
|
||||
lara.RightArm.FrameBase = Objects[GetWeaponObjectID(lara.Control.Weapon.GunType)].frameBase;
|
||||
lara.LeftArm.FrameBase = Objects[GetWeaponObjectID(lara.Control.Weapon.GunType)].frameBase;
|
||||
player.RightArm.FrameBase = Objects[GetWeaponObjectID(player.Control.Weapon.GunType)].frameBase;
|
||||
player.LeftArm.FrameBase = Objects[GetWeaponObjectID(player.Control.Weapon.GunType)].frameBase;
|
||||
|
||||
if (lara.Control.HandStatus != HandStatus::Free)
|
||||
DrawShotgunMeshes(laraItem, lara.Control.Weapon.GunType);
|
||||
if (player.Control.HandStatus != HandStatus::Free)
|
||||
DrawShotgunMeshes(laraItem, player.Control.Weapon.GunType);
|
||||
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Flare:
|
||||
lara.RightArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
||||
lara.LeftArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
||||
player.RightArm.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);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
lara.RightArm.FrameBase = g_Level.Anims[laraItem->Animation.AnimNumber].FramePtr;
|
||||
lara.LeftArm.FrameBase = g_Level.Anims[laraItem->Animation.AnimNumber].FramePtr;
|
||||
player.RightArm.FrameBase = g_Level.Anims[laraItem.Animation.AnimNumber].FramePtr;
|
||||
player.LeftArm.FrameBase = g_Level.Anims[laraItem.Animation.AnimNumber].FramePtr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -346,23 +348,23 @@ Ammo& GetAmmo(LaraInfo& lara, LaraWeaponType weaponType)
|
|||
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(
|
||||
(bounds.X1 + bounds.X2) / 2,
|
||||
bounds.Y1 + (bounds.GetHeight() / 3),
|
||||
(bounds.Z1 + bounds.Z2) / 2);
|
||||
|
||||
float sinY = phd_sin(targetEntity->Pose.Orientation.y);
|
||||
float cosY = phd_cos(targetEntity->Pose.Orientation.y);
|
||||
float sinY = phd_sin(targetEntity.Pose.Orientation.y);
|
||||
float cosY = phd_cos(targetEntity.Pose.Orientation.y);
|
||||
|
||||
return GameVector(
|
||||
targetEntity->Pose.Position.x + ((center.x * cosY) + (center.z * sinY)),
|
||||
targetEntity->Pose.Position.y + center.y,
|
||||
targetEntity->Pose.Position.z + ((center.z * cosY) - (center.x * sinY)),
|
||||
targetEntity->RoomNumber);
|
||||
targetEntity.Pose.Position.x + ((center.x * cosY) + (center.z * sinY)),
|
||||
targetEntity.Pose.Position.y + center.y,
|
||||
targetEntity.Pose.Position.z + ((center.z * cosY) - (center.x * sinY)),
|
||||
targetEntity.RoomNumber);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
return ID_UZI_ANIM;
|
||||
|
@ -456,7 +458,7 @@ GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo* laraItem, LaraWeaponType weaponTy
|
|||
return ID_HK_ANIM;
|
||||
|
||||
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:
|
||||
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)
|
||||
--lara.LeftArm.GunFlash;
|
||||
if (player.LeftArm.GunFlash > 0)
|
||||
--player.LeftArm.GunFlash;
|
||||
|
||||
if (lara.RightArm.GunFlash > 0)
|
||||
--lara.RightArm.GunFlash;
|
||||
if (player.RightArm.GunFlash > 0)
|
||||
--player.RightArm.GunFlash;
|
||||
|
||||
if (lara.RightArm.GunSmoke > 0)
|
||||
--lara.RightArm.GunSmoke;
|
||||
if (player.RightArm.GunSmoke > 0)
|
||||
--player.RightArm.GunSmoke;
|
||||
|
||||
if (lara.LeftArm.GunSmoke > 0)
|
||||
--lara.LeftArm.GunSmoke;
|
||||
if (player.LeftArm.GunSmoke > 0)
|
||||
--player.LeftArm.GunSmoke;
|
||||
|
||||
if (FlashGrenadeAftershockTimer)
|
||||
FlashGrenadeAftershockTimer--;
|
||||
|
||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Torch)
|
||||
if (player.Control.Weapon.GunType == LaraWeaponType::Torch)
|
||||
{
|
||||
DoFlameTorch();
|
||||
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.
|
||||
if (IsHeld(In::DrawWeapon))
|
||||
{
|
||||
// No weapon - no any actions.
|
||||
if (lara.Control.Weapon.LastGunType != LaraWeaponType::None)
|
||||
lara.Control.Weapon.RequestGunType = lara.Control.Weapon.LastGunType;
|
||||
if (player.Control.Weapon.LastGunType != LaraWeaponType::None)
|
||||
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||
}
|
||||
// Draw flare.
|
||||
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)
|
||||
lara.Inventory.TotalFlares--;
|
||||
if (player.Inventory.TotalFlares != -1)
|
||||
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) ||
|
||||
lara.Control.Weapon.RequestGunType != lara.Control.Weapon.GunType)
|
||||
if ((IsHeld(In::DrawWeapon) && player.Control.Weapon.LastGunType != LaraWeaponType::None) ||
|
||||
player.Control.Weapon.RequestGunType != player.Control.Weapon.GunType)
|
||||
{
|
||||
if (lara.Control.IsLow &&
|
||||
lara.Control.Weapon.RequestGunType >= LaraWeaponType::Shotgun &&
|
||||
lara.Control.Weapon.RequestGunType != LaraWeaponType::Flare &&
|
||||
lara.Control.Weapon.RequestGunType != LaraWeaponType::Torch)
|
||||
if (player.Control.IsLow &&
|
||||
player.Control.Weapon.RequestGunType >= LaraWeaponType::Shotgun &&
|
||||
player.Control.Weapon.RequestGunType != LaraWeaponType::Flare &&
|
||||
player.Control.Weapon.RequestGunType != LaraWeaponType::Torch)
|
||||
{
|
||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||
lara.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||
player.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||
}
|
||||
else if (lara.Control.Weapon.RequestGunType == LaraWeaponType::Flare ||
|
||||
(lara.Vehicle == NO_ITEM &&
|
||||
(lara.Control.Weapon.RequestGunType == LaraWeaponType::HarpoonGun ||
|
||||
lara.Control.WaterStatus == WaterStatus::Dry ||
|
||||
(lara.Control.WaterStatus == WaterStatus::Wade &&
|
||||
lara.WaterSurfaceDist > -Weapons[(int)lara.Control.Weapon.GunType].GunHeight))))
|
||||
else if (player.Control.Weapon.RequestGunType == LaraWeaponType::Flare ||
|
||||
(player.Context.Vehicle == NO_ITEM &&
|
||||
(player.Control.Weapon.RequestGunType == LaraWeaponType::HarpoonGun ||
|
||||
player.Control.WaterStatus == WaterStatus::Dry ||
|
||||
(player.Control.WaterStatus == WaterStatus::Wade &&
|
||||
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);
|
||||
UndrawFlareMeshes(laraItem);
|
||||
lara.Flare.ControlLeft = false;
|
||||
lara.Flare.Life = 0;
|
||||
player.Flare.ControlLeft = false;
|
||||
player.Flare.Life = 0;
|
||||
}
|
||||
|
||||
lara.Control.Weapon.GunType = lara.Control.Weapon.RequestGunType;
|
||||
InitialiseNewWeapon(laraItem);
|
||||
lara.RightArm.FrameNumber = 0;
|
||||
lara.LeftArm.FrameNumber = 0;
|
||||
lara.Control.HandStatus = HandStatus::WeaponDraw;
|
||||
player.Control.Weapon.GunType = player.Control.Weapon.RequestGunType;
|
||||
InitializeNewWeapon(laraItem);
|
||||
player.RightArm.FrameNumber = 0;
|
||||
player.LeftArm.FrameNumber = 0;
|
||||
player.Control.HandStatus = HandStatus::WeaponDraw;
|
||||
}
|
||||
else
|
||||
{
|
||||
lara.Control.Weapon.LastGunType = lara.Control.Weapon.RequestGunType;
|
||||
player.Control.Weapon.LastGunType = player.Control.Weapon.RequestGunType;
|
||||
|
||||
if (lara.Control.Weapon.GunType != LaraWeaponType::Flare)
|
||||
lara.Control.Weapon.GunType = lara.Control.Weapon.RequestGunType;
|
||||
if (player.Control.Weapon.GunType != LaraWeaponType::Flare)
|
||||
{
|
||||
player.Control.Weapon.GunType = player.Control.Weapon.RequestGunType;
|
||||
}
|
||||
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) ||
|
||||
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 &&
|
||||
lara.Control.WaterStatus != WaterStatus::Dry &&
|
||||
(lara.Control.WaterStatus != WaterStatus::Wade ||
|
||||
lara.WaterSurfaceDist < -Weapons[(int)lara.Control.Weapon.GunType].GunHeight))
|
||||
else if (player.Control.Weapon.GunType != LaraWeaponType::HarpoonGun &&
|
||||
player.Control.WaterStatus != WaterStatus::Dry &&
|
||||
(player.Control.WaterStatus != WaterStatus::Wade ||
|
||||
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) &&
|
||||
lara.Control.HandStatus == HandStatus::Busy &&
|
||||
laraItem->Animation.ActiveState == LS_CRAWL_IDLE &&
|
||||
laraItem->Animation.AnimNumber == LA_CRAWL_IDLE)
|
||||
player.Control.HandStatus == HandStatus::Busy &&
|
||||
laraItem.Animation.ActiveState == LS_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:
|
||||
if (lara.Control.Weapon.GunType != LaraWeaponType::Flare &&
|
||||
lara.Control.Weapon.GunType != LaraWeaponType::None)
|
||||
if (player.Control.Weapon.GunType != LaraWeaponType::Flare &&
|
||||
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::Revolver:
|
||||
|
@ -612,7 +618,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
||||
Camera.type = CameraType::Combat;
|
||||
|
||||
DrawPistols(laraItem, lara.Control.Weapon.GunType);
|
||||
DrawPistols(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Shotgun:
|
||||
|
@ -624,7 +630,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
||||
Camera.type = CameraType::Combat;
|
||||
|
||||
DrawShotgun(laraItem, lara.Control.Weapon.GunType);
|
||||
DrawShotgun(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Flare:
|
||||
|
@ -632,7 +638,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
break;
|
||||
|
||||
default:
|
||||
lara.Control.HandStatus = HandStatus::Free;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -643,14 +649,14 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
break;
|
||||
|
||||
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::Revolver:
|
||||
case LaraWeaponType::Uzi:
|
||||
UndrawPistols(laraItem, lara.Control.Weapon.GunType);
|
||||
UndrawPistols(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Shotgun:
|
||||
|
@ -659,7 +665,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
case LaraWeaponType::GrenadeLauncher:
|
||||
case LaraWeaponType::RocketLauncher:
|
||||
case LaraWeaponType::HarpoonGun:
|
||||
UndrawShotgun(laraItem, lara.Control.Weapon.GunType);
|
||||
UndrawShotgun(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Flare:
|
||||
|
@ -674,9 +680,13 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
|
||||
case HandStatus::WeaponReady:
|
||||
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
|
||||
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 &&
|
||||
Camera.type != CameraType::Heavy)
|
||||
|
@ -686,19 +696,19 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
|
||||
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);
|
||||
lara.Control.Weapon.RequestGunType = hasPistols ? LaraWeaponType::Pistol : LaraWeaponType::None;
|
||||
bool hasPistols = (player.Weapons[(int)LaraWeaponType::Pistol].Present && Objects[ID_PISTOLS_ITEM].loaded);
|
||||
player.Control.Weapon.RequestGunType = hasPistols ? LaraWeaponType::Pistol : LaraWeaponType::None;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lara.Control.Weapon.GunType)
|
||||
switch (player.Control.Weapon.GunType)
|
||||
{
|
||||
case LaraWeaponType::Pistol:
|
||||
case LaraWeaponType::Uzi:
|
||||
PistolHandler(laraItem, lara.Control.Weapon.GunType);
|
||||
HandlePistols(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
case LaraWeaponType::Shotgun:
|
||||
|
@ -708,8 +718,8 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
case LaraWeaponType::RocketLauncher:
|
||||
case LaraWeaponType::HarpoonGun:
|
||||
case LaraWeaponType::Revolver:
|
||||
RifleHandler(laraItem, lara.Control.Weapon.GunType);
|
||||
LasersightWeaponHandler(laraItem, lara.Control.Weapon.GunType);
|
||||
RifleHandler(laraItem, player.Control.Weapon.GunType);
|
||||
LasersightWeaponHandler(laraItem, player.Control.Weapon.GunType);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -719,43 +729,43 @@ void HandleWeapon(ItemInfo* laraItem)
|
|||
break;
|
||||
|
||||
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)
|
||||
lara.LeftArm.FrameNumber = 0;
|
||||
if (++player.LeftArm.FrameNumber == 110)
|
||||
player.LeftArm.FrameNumber = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara.LeftArm.FrameNumber = 95;
|
||||
lara.Flare.ControlLeft = true;
|
||||
player.LeftArm.FrameNumber = 95;
|
||||
player.Flare.ControlLeft = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara.Flare.ControlLeft = false;
|
||||
player.Flare.ControlLeft = false;
|
||||
}
|
||||
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
SetFlareArm(laraItem, player.LeftArm.FrameNumber);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
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));
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
||||
player.Flare.ControlLeft = (player.Context.Vehicle != NO_ITEM || TestState(laraItem.Animation.ActiveState, FlarePoseStates));
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
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);
|
||||
}
|
||||
|
||||
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& ammo = GetAmmo(lara, weaponType);
|
||||
auto& player = *GetLaraInfo(&laraItem);
|
||||
auto& ammo = GetAmmo(player, weaponType);
|
||||
|
||||
if (ammo.GetCount() == 0 && !ammo.HasInfinite())
|
||||
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,
|
||||
0);
|
||||
|
||||
auto muzzleOffset = GetJointPosition(laraItem, LM_RHAND);
|
||||
auto pos = Vector3i(laraItem->Pose.Position.x, muzzleOffset.y, laraItem->Pose.Position.z);
|
||||
auto muzzleOffset = GetJointPosition(&laraItem, LM_RHAND);
|
||||
auto pos = Vector3i(laraItem.Pose.Position.x, muzzleOffset.y, laraItem.Pose.Position.z);
|
||||
|
||||
// Calculate ray from wobbled orientation.
|
||||
auto directionNorm = wobbledArmOrient.ToDirection();
|
||||
|
@ -798,7 +809,7 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
|||
auto target = origin + (directionNorm * weapon.TargetDist);
|
||||
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;
|
||||
float bestDistance = INFINITY;
|
||||
for (int i = 0; i < num; i++)
|
||||
|
@ -815,11 +826,11 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
|||
}
|
||||
}
|
||||
|
||||
lara.Control.Weapon.HasFired = true;
|
||||
lara.Control.Weapon.Fired = true;
|
||||
player.Control.Weapon.HasFired = true;
|
||||
player.Control.Weapon.Fired = true;
|
||||
|
||||
auto vOrigin = GameVector(pos);
|
||||
short roomNumber = laraItem->RoomNumber;
|
||||
short roomNumber = laraItem.RoomNumber;
|
||||
GetFloor(pos.x, pos.y, pos.z, &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.
|
||||
// It's strange, but this replicates original behaviour until we fully understand what is happening.
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
||||
void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo)
|
||||
{
|
||||
if (!g_Configuration.AutoTarget)
|
||||
return;
|
||||
|
||||
auto& lara = *GetLaraInfo(laraItem);
|
||||
auto& player = *GetLaraInfo(&laraItem);
|
||||
|
||||
if (BinocularRange)
|
||||
{
|
||||
lara.TargetEntity = nullptr;
|
||||
player.TargetEntity = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
auto origin = GameVector(
|
||||
laraItem->Pose.Position.x,
|
||||
GetJointPosition(laraItem, LM_RHAND).y, // Muzzle offset.
|
||||
laraItem->Pose.Position.z,
|
||||
laraItem->RoomNumber);
|
||||
laraItem.Pose.Position.x,
|
||||
GetJointPosition(&laraItem, LM_RHAND).y, // Muzzle offset.
|
||||
laraItem.Pose.Position.z,
|
||||
laraItem.RoomNumber);
|
||||
|
||||
ItemInfo* bestEntity = nullptr;
|
||||
float bestDistance = INFINITY;
|
||||
short bestYOrient = MAXSHORT;
|
||||
unsigned int numTargets = 0;
|
||||
ItemInfo* closestEntityPtr = nullptr;
|
||||
|
||||
float closestDistance = INFINITY;
|
||||
short closestHeadingAngle = MAXSHORT;
|
||||
unsigned int targetCount = 0;
|
||||
float maxDistance = weaponInfo.TargetDist;
|
||||
|
||||
for (auto* activeCreature : ActiveCreatures)
|
||||
for (auto* creaturePtr : ActiveCreatures)
|
||||
{
|
||||
// Continue loop if no item.
|
||||
if (activeCreature->ItemNumber == NO_ITEM)
|
||||
if (creaturePtr->ItemNumber == NO_ITEM)
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
@ -887,64 +899,64 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
|||
continue;
|
||||
|
||||
// Assess line of sight.
|
||||
auto target = GetTargetPoint(&item);
|
||||
auto target = GetTargetPoint(item);
|
||||
if (!LOS(&origin, &target))
|
||||
continue;
|
||||
|
||||
// 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 &&
|
||||
orient.y >= weaponInfo.LockOrientConstraint.first.y &&
|
||||
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
||||
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
||||
{
|
||||
TargetList[numTargets] = &item;
|
||||
++numTargets;
|
||||
TargetList[targetCount] = &item;
|
||||
++targetCount;
|
||||
|
||||
if (distance < bestDistance &&
|
||||
abs(orient.y) < (bestYOrient + ANGLE(15.0f)))
|
||||
if (distance < closestDistance &&
|
||||
abs(orient.y) < (closestHeadingAngle + ANGLE(15.0f)))
|
||||
{
|
||||
bestEntity = &item;
|
||||
bestDistance = distance;
|
||||
bestYOrient = abs(orient.y);
|
||||
closestEntityPtr = &item;
|
||||
closestDistance = distance;
|
||||
closestHeadingAngle = abs(orient.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TargetList[numTargets] = nullptr;
|
||||
if (!TargetList[0])
|
||||
TargetList[targetCount] = nullptr;
|
||||
if (TargetList[0] == nullptr)
|
||||
{
|
||||
lara.TargetEntity = nullptr;
|
||||
player.TargetEntity = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int slot = 0; slot < MAX_TARGETS; ++slot)
|
||||
for (const auto* targetPtr : TargetList)
|
||||
{
|
||||
if (!TargetList[slot])
|
||||
lara.TargetEntity = nullptr;
|
||||
if (targetPtr == nullptr)
|
||||
player.TargetEntity = nullptr;
|
||||
|
||||
if (TargetList[slot] == lara.TargetEntity)
|
||||
if (targetPtr == player.TargetEntity)
|
||||
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;
|
||||
}
|
||||
else if (IsClicked(In::SwitchTarget))
|
||||
{
|
||||
lara.TargetEntity = nullptr;
|
||||
player.TargetEntity = nullptr;
|
||||
bool flag = true;
|
||||
|
||||
for (int match = 0; match < MAX_TARGETS && TargetList[match]; ++match)
|
||||
for (const auto& targetPtr : TargetList)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
|
@ -953,8 +965,8 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
|||
|
||||
if (!doLoop)
|
||||
{
|
||||
lara.TargetEntity = TargetList[match];
|
||||
if (lara.TargetEntity)
|
||||
player.TargetEntity = targetPtr;
|
||||
if (player.TargetEntity)
|
||||
flag = false;
|
||||
|
||||
break;
|
||||
|
@ -963,44 +975,44 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
|||
|
||||
if (flag)
|
||||
{
|
||||
lara.TargetEntity = bestEntity;
|
||||
player.TargetEntity = closestEntityPtr;
|
||||
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[0] = lara.TargetEntity;
|
||||
LastTargets[0] = player.TargetEntity;
|
||||
}
|
||||
|
||||
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;
|
||||
lara.LeftArm.Locked = false;
|
||||
lara.TargetArmOrient = EulerAngles::Zero;
|
||||
player.RightArm.Locked = false;
|
||||
player.LeftArm.Locked = false;
|
||||
player.TargetArmOrient = EulerAngles::Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
auto origin = GameVector(
|
||||
laraItem->Pose.Position.x,
|
||||
GetJointPosition(laraItem, LM_RHAND).y, // Muzzle offset.
|
||||
laraItem->Pose.Position.z,
|
||||
laraItem->RoomNumber);
|
||||
auto target = GetTargetPoint(lara.TargetEntity);
|
||||
laraItem.Pose.Position.x,
|
||||
GetJointPosition(&laraItem, LM_RHAND).y, // Muzzle offset.
|
||||
laraItem.Pose.Position.z,
|
||||
laraItem.RoomNumber);
|
||||
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))
|
||||
{
|
||||
|
@ -1009,41 +1021,41 @@ void LaraTargetInfo(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
|||
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
||||
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
||||
{
|
||||
lara.RightArm.Locked = true;
|
||||
lara.LeftArm.Locked = true;
|
||||
player.RightArm.Locked = true;
|
||||
player.LeftArm.Locked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lara.LeftArm.Locked)
|
||||
if (player.LeftArm.Locked)
|
||||
{
|
||||
if (orient.x < weaponInfo.LeftOrientConstraint.first.x ||
|
||||
orient.y < weaponInfo.LeftOrientConstraint.first.y ||
|
||||
orient.x > weaponInfo.LeftOrientConstraint.second.x ||
|
||||
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 ||
|
||||
orient.y < weaponInfo.RightOrientConstraint.first.y ||
|
||||
orient.x > weaponInfo.RightOrientConstraint.second.x ||
|
||||
orient.y > weaponInfo.RightOrientConstraint.second.y)
|
||||
{
|
||||
lara.RightArm.Locked = false;
|
||||
player.RightArm.Locked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara.RightArm.Locked = false;
|
||||
lara.LeftArm.Locked = false;
|
||||
player.RightArm.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)
|
||||
|
|
|
@ -5,8 +5,6 @@ class EulerAngles;
|
|||
struct CollisionInfo;
|
||||
struct ItemInfo;
|
||||
|
||||
constexpr auto MAX_TARGETS = 8;
|
||||
|
||||
enum class FireWeaponType
|
||||
{
|
||||
Miss = -1,
|
||||
|
@ -48,20 +46,20 @@ struct WeaponInfo
|
|||
extern int FlashGrenadeAftershockTimer;
|
||||
extern WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons];
|
||||
|
||||
void InitialiseNewWeapon(ItemInfo* laraItem);
|
||||
void InitializeNewWeapon(ItemInfo& laraItem);
|
||||
|
||||
Ammo& GetAmmo(LaraInfo& lara, LaraWeaponType weaponType);
|
||||
GameVector GetTargetPoint(ItemInfo* targetEntity);
|
||||
GameVector GetTargetPoint(ItemInfo& targetEntity);
|
||||
HolsterSlot GetWeaponHolsterSlot(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 AimWeapon(ItemInfo* laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo);
|
||||
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, ItemInfo* laraItem, const EulerAngles& armOrient);
|
||||
void HandleWeapon(ItemInfo& laraItem);
|
||||
void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo);
|
||||
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient);
|
||||
|
||||
void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo);
|
||||
void LaraTargetInfo(ItemInfo* laraItem, const WeaponInfo& weaponInfo);
|
||||
void FindNewTarget(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 SmashItem(short itemNumber);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Game/animation.h"
|
||||
#include "Game/camera.h"
|
||||
#include "Game/collision/collide_item.h"
|
||||
#include "Game/control/control.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/chaffFX.h"
|
||||
#include "Game/items.h"
|
||||
|
@ -11,16 +12,16 @@
|
|||
#include "Game/Lara/lara_fire.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
constexpr auto FLARE_LIFE_MAX = 60 * FPS;
|
||||
constexpr auto FLARE_LIGHT_COLOR = Vector3(0.8f, 0.42947f, 0.2921f);
|
||||
constexpr auto FLARE_LIFE_MAX = 60.0f * FPS;
|
||||
constexpr auto FLARE_LIGHT_COLOR = Vector3(0.8f, 0.43f, 0.3f);
|
||||
|
||||
void FlareControl(short itemNumber)
|
||||
{
|
||||
|
@ -43,13 +44,13 @@ void FlareControl(short itemNumber)
|
|||
flareItem.Pose.Orientation.z = 0;
|
||||
}
|
||||
|
||||
auto velocity = Vector3i(
|
||||
auto vel = Vector3i(
|
||||
flareItem.Animation.Velocity.z * phd_sin(flareItem.Pose.Orientation.y),
|
||||
flareItem.Animation.Velocity.y,
|
||||
flareItem.Animation.Velocity.z * phd_cos(flareItem.Pose.Orientation.y));
|
||||
|
||||
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) ||
|
||||
TestEnvironment(ENV_FLAG_SWAMP, &flareItem))
|
||||
|
@ -63,13 +64,14 @@ void FlareControl(short itemNumber)
|
|||
}
|
||||
|
||||
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;
|
||||
life &= 0x7FFF;
|
||||
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);
|
||||
return;
|
||||
|
@ -83,91 +85,89 @@ void FlareControl(short itemNumber)
|
|||
if (DoFlareLight(flareItem.Pose.Position, life))
|
||||
{
|
||||
TriggerChaffEffects(flareItem, life);
|
||||
/* Hardcoded code */
|
||||
|
||||
life |= 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadyFlare(ItemInfo* laraItem)
|
||||
void ReadyFlare(ItemInfo& laraItem)
|
||||
{
|
||||
auto& lara = *GetLaraInfo(laraItem);
|
||||
auto& player = *GetLaraInfo(&laraItem);
|
||||
|
||||
lara.Control.HandStatus = HandStatus::Free;
|
||||
lara.LeftArm.Orientation = EulerAngles::Zero;
|
||||
lara.RightArm.Orientation = EulerAngles::Zero;
|
||||
lara.LeftArm.Locked = false;
|
||||
lara.RightArm.Locked = false;
|
||||
lara.TargetEntity = nullptr;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
player.LeftArm.Orientation =
|
||||
player.RightArm.Orientation = EulerAngles::Zero;
|
||||
player.LeftArm.Locked =
|
||||
player.RightArm.Locked = false;
|
||||
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 armFrame = lara.LeftArm.FrameNumber;
|
||||
int flareFrame = player.Flare.Frame;
|
||||
int armFrame = player.LeftArm.FrameNumber;
|
||||
|
||||
lara.Flare.ControlLeft = true;
|
||||
player.Flare.ControlLeft = true;
|
||||
|
||||
if (laraItem->Animation.TargetState == LS_IDLE &&
|
||||
lara.Vehicle == NO_ITEM)
|
||||
if (laraItem.Animation.TargetState == LS_IDLE &&
|
||||
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;
|
||||
flareFrame = armFrame + g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||
laraItem->Animation.FrameNumber = flareFrame;
|
||||
lara.Flare.Frame = flareFrame;
|
||||
laraItem.Animation.AnimNumber = LA_DISCARD_FLARE;
|
||||
flareFrame = armFrame + g_Level.Anims[laraItem.Animation.AnimNumber].frameBase;
|
||||
laraItem.Animation.FrameNumber = 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;
|
||||
lara.Control.Weapon.GunType = lara.Control.Weapon.LastGunType;
|
||||
lara.Control.HandStatus = HandStatus::Free;
|
||||
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||
player.Control.Weapon.GunType = player.Control.Weapon.LastGunType;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
|
||||
InitialiseNewWeapon(laraItem);
|
||||
InitializeNewWeapon(laraItem);
|
||||
|
||||
lara.TargetEntity = nullptr;
|
||||
lara.RightArm.Locked = false;
|
||||
lara.LeftArm.Locked = false;
|
||||
SetAnimation(laraItem, LA_STAND_IDLE);
|
||||
lara.Flare.Frame = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||
player.TargetEntity = nullptr;
|
||||
player.LeftArm.Locked =
|
||||
player.RightArm.Locked = false;
|
||||
SetAnimation(&laraItem, LA_STAND_IDLE);
|
||||
player.Flare.Frame = g_Level.Anims[laraItem.Animation.AnimNumber].frameBase;
|
||||
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)
|
||||
{
|
||||
armFrame = 2;
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
else if (!armFrame)
|
||||
{
|
||||
armFrame = 1;
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
else if (armFrame >= 72 && armFrame < 95)
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ void UndrawFlare(ItemInfo* laraItem)
|
|||
if (armFrame == 94)
|
||||
{
|
||||
armFrame = 1;
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
}
|
||||
else if (armFrame >= 1 && armFrame < 33)
|
||||
|
@ -187,27 +187,27 @@ void UndrawFlare(ItemInfo* laraItem)
|
|||
{
|
||||
CreateFlare(laraItem, ID_FLARE_ITEM, true);
|
||||
UndrawFlareMeshes(laraItem);
|
||||
lara.Flare.Life = 0;
|
||||
player.Flare.Life = 0;
|
||||
}
|
||||
else if (armFrame == 33)
|
||||
{
|
||||
armFrame = 0;
|
||||
|
||||
lara.Control.Weapon.RequestGunType = lara.Control.Weapon.LastGunType;
|
||||
lara.Control.Weapon.GunType = lara.Control.Weapon.LastGunType;
|
||||
lara.Control.HandStatus = HandStatus::Free;
|
||||
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||
player.Control.Weapon.GunType = player.Control.Weapon.LastGunType;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
|
||||
InitialiseNewWeapon(laraItem);
|
||||
InitializeNewWeapon(laraItem);
|
||||
|
||||
lara.TargetEntity = nullptr;
|
||||
lara.LeftArm.Locked = false;
|
||||
lara.RightArm.Locked = false;
|
||||
lara.Flare.ControlLeft = false;
|
||||
lara.Flare.Frame = 0;
|
||||
player.TargetEntity = nullptr;
|
||||
player.LeftArm.Locked =
|
||||
player.RightArm.Locked = false;
|
||||
player.Flare.ControlLeft = false;
|
||||
player.Flare.Frame = 0;
|
||||
}
|
||||
else if (armFrame < 21)
|
||||
{
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
}
|
||||
else if (armFrame >= 95 && armFrame < 110)
|
||||
|
@ -217,30 +217,30 @@ void UndrawFlare(ItemInfo* laraItem)
|
|||
if (armFrame == 110)
|
||||
{
|
||||
armFrame = 1;
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
}
|
||||
|
||||
lara.LeftArm.FrameNumber = armFrame;
|
||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
||||
player.LeftArm.FrameNumber = armFrame;
|
||||
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 ||
|
||||
laraItem->Animation.ActiveState == LS_PICKUP)
|
||||
if (laraItem.Animation.ActiveState == LS_PICKUP_FLARE ||
|
||||
laraItem.Animation.ActiveState == LS_PICKUP)
|
||||
{
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
lara.Flare.ControlLeft = false;
|
||||
lara.LeftArm.FrameNumber = 93;
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
player.Flare.ControlLeft = false;
|
||||
player.LeftArm.FrameNumber = 93;
|
||||
SetFlareArm(laraItem, 93);
|
||||
}
|
||||
else
|
||||
{
|
||||
int armFrame = lara.LeftArm.FrameNumber + 1;
|
||||
lara.Flare.ControlLeft = true;
|
||||
int armFrame = player.LeftArm.FrameNumber + 1;
|
||||
player.Flare.ControlLeft = true;
|
||||
|
||||
if (armFrame < 33 || armFrame > 94)
|
||||
{
|
||||
|
@ -254,11 +254,14 @@ void DrawFlare(ItemInfo* laraItem)
|
|||
{
|
||||
if (armFrame == 72)
|
||||
{
|
||||
SoundEffect(SFX_TR4_FLARE_IGNITE_DRY, &laraItem->Pose, TestEnvironment(ENV_FLAG_WATER, laraItem) ? SoundEnvironment::Water : SoundEnvironment::Land);
|
||||
lara.Flare.Life = 1;
|
||||
player.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
|
||||
{
|
||||
|
@ -266,18 +269,18 @@ void DrawFlare(ItemInfo* laraItem)
|
|||
{
|
||||
ReadyFlare(laraItem);
|
||||
armFrame = 0;
|
||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
||||
DoFlareInHand(laraItem, player.Flare.Life);
|
||||
}
|
||||
}
|
||||
|
||||
lara.LeftArm.FrameNumber = armFrame;
|
||||
player.LeftArm.FrameNumber = 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;
|
||||
|
||||
if (armFrame >= 95)
|
||||
|
@ -297,13 +300,13 @@ void SetFlareArm(ItemInfo* laraItem, int armFrame)
|
|||
flareAnimNum += 1;
|
||||
}
|
||||
|
||||
lara.LeftArm.AnimNumber = flareAnimNum;
|
||||
lara.LeftArm.FrameBase = g_Level.Anims[flareAnimNum].FramePtr;
|
||||
player.LeftArm.AnimNumber = flareAnimNum;
|
||||
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();
|
||||
if (itemNumber == NO_ITEM)
|
||||
|
@ -311,36 +314,40 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
|||
|
||||
auto& flareItem = g_Level.Items[itemNumber];
|
||||
|
||||
flareItem.ObjectNumber = objectNumber;
|
||||
flareItem.RoomNumber = laraItem->RoomNumber;
|
||||
flareItem.ObjectNumber = objectID;
|
||||
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;
|
||||
|
||||
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);
|
||||
bool hasLanded = false;
|
||||
|
||||
if (floorHeight < pos.y || hasCollided)
|
||||
{
|
||||
hasLanded = true;
|
||||
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.Orientation.y = laraItem->Pose.Orientation.y + ANGLE(180.0f);
|
||||
flareItem.RoomNumber = laraItem->RoomNumber;
|
||||
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.Orientation.y = laraItem.Pose.Orientation.y + ANGLE(180.0f);
|
||||
flareItem.RoomNumber = laraItem.RoomNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isThrown)
|
||||
flareItem.Pose.Orientation.y = laraItem->Pose.Orientation.y;
|
||||
{
|
||||
flareItem.Pose.Orientation.y = laraItem.Pose.Orientation.y;
|
||||
}
|
||||
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.z = 0;
|
||||
|
@ -348,19 +355,19 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
|||
|
||||
if (isThrown)
|
||||
{
|
||||
flareItem.Animation.Velocity.z = laraItem->Animation.Velocity.z + 50;
|
||||
flareItem.Animation.Velocity.y = laraItem->Animation.Velocity.y - 50;
|
||||
flareItem.Animation.Velocity.z = laraItem.Animation.Velocity.z + 50;
|
||||
flareItem.Animation.Velocity.y = laraItem.Animation.Velocity.y - 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
flareItem.Animation.Velocity.z = laraItem->Animation.Velocity.z + 10;
|
||||
flareItem.Animation.Velocity.y = laraItem->Animation.Velocity.y + 50;
|
||||
flareItem.Animation.Velocity.z = laraItem.Animation.Velocity.z + 10;
|
||||
flareItem.Animation.Velocity.y = laraItem.Animation.Velocity.y + 50;
|
||||
}
|
||||
|
||||
if (hasLanded)
|
||||
flareItem.Animation.Velocity.z /= 2;
|
||||
|
||||
if (objectNumber == ID_FLARE_ITEM)
|
||||
if (objectID == ID_FLARE_ITEM)
|
||||
{
|
||||
flareItem.Data = (int)0;
|
||||
int& life = flareItem.Data;
|
||||
|
@ -379,28 +386,21 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
|||
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& lara = *GetLaraInfo(laraItem);
|
||||
|
||||
auto pos = GetJointPosition(laraItem, LM_LHAND, Vector3i(11, 32, 41));
|
||||
auto pos = GetJointPosition(&laraItem, LM_LHAND, Vector3i(11, 32, 41));
|
||||
|
||||
if (DoFlareLight(pos, flareLife))
|
||||
TriggerChaffEffects(BinocularOn ? 0 : flareLife);
|
||||
|
||||
/* Hardcoded code */
|
||||
|
||||
if (lara.Flare.Life >= FLARE_LIFE_MAX)
|
||||
{
|
||||
// Prevent Lara from intercepting reach/jump states with flare throws.
|
||||
if (laraItem->Animation.IsAirborne ||
|
||||
laraItem->Animation.TargetState == LS_JUMP_PREPARE ||
|
||||
laraItem->Animation.TargetState == LS_JUMP_FORWARD)
|
||||
// Prevent player from intercepting reach/jump states with flare throws.
|
||||
if (laraItem.Animation.IsAirborne ||
|
||||
laraItem.Animation.TargetState == LS_JUMP_PREPARE ||
|
||||
laraItem.Animation.TargetState == LS_JUMP_FORWARD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -419,53 +419,39 @@ bool DoFlareLight(const Vector3i& pos, int flareLife)
|
|||
if (flareLife >= FLARE_LIFE_MAX || flareLife == 0)
|
||||
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(
|
||||
randomFloat * 120,
|
||||
(randomFloat * 120) - CLICK(1),
|
||||
randomFloat * 120);
|
||||
|
||||
bool result = false;
|
||||
bool spawnChaff = false;
|
||||
bool isEnding = (flareLife > (FLARE_LIFE_MAX - 90));
|
||||
bool isDying = (flareLife > (FLARE_LIFE_MAX - 5));
|
||||
|
||||
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;
|
||||
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);
|
||||
spawnChaff = Random::TestProbability(9 / 10.0f);
|
||||
}
|
||||
else if (isEnding)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
spawnChaff = Random::TestProbability(2 / 5.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
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);
|
||||
spawnChaff = Random::TestProbability(3 / 10.0f);
|
||||
}
|
||||
|
||||
return ((isDying || isEnding) ? result : true);
|
||||
return ((isDying || isEnding) ? spawnChaff : true);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
#pragma once
|
||||
#include "Game/control/control.h"
|
||||
|
||||
enum GAME_OBJECT_ID : short;
|
||||
class Vector3i;
|
||||
struct CollisionInfo;
|
||||
struct ItemInfo;
|
||||
class Vector3i;
|
||||
enum GAME_OBJECT_ID : short;
|
||||
|
||||
void FlareControl(short itemNumber);
|
||||
void ReadyFlare(ItemInfo* laraItem);
|
||||
void UndrawFlareMeshes(ItemInfo* laraItem);
|
||||
void DrawFlareMeshes(ItemInfo* laraItem);
|
||||
void UndrawFlare(ItemInfo* laraItem);
|
||||
void DrawFlare(ItemInfo* laraItem);
|
||||
void SetFlareArm(ItemInfo* laraItem, int armFrame);
|
||||
void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown);
|
||||
void DrawFlareInAir(ItemInfo* flareItem);
|
||||
void DoFlareInHand(ItemInfo* laraItem, int flareLife);
|
||||
void ReadyFlare(ItemInfo& laraItem);
|
||||
|
||||
void UndrawFlareMeshes(ItemInfo& laraItem);
|
||||
void DrawFlareMeshes(ItemInfo& laraItem);
|
||||
|
||||
void UndrawFlare(ItemInfo& laraItem);
|
||||
void DrawFlare(ItemInfo& laraItem);
|
||||
|
||||
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);
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
#include "Game/Lara/lara_collide.h"
|
||||
#include "Game/Lara/lara_fire.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Scripting/Include/ScriptInterfaceLevel.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
#include "Objects/TR2/Vehicles/skidoo.h"
|
||||
#include "Objects/TR3/Vehicles/big_gun.h"
|
||||
|
@ -33,7 +33,7 @@
|
|||
using namespace TEN::Control::Volumes;
|
||||
using namespace TEN::Effects::Bubble;
|
||||
using namespace TEN::Effects::Drip;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Input;
|
||||
using namespace TEN::Math;
|
||||
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)))) &&
|
||||
(!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.
|
||||
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)))))
|
||||
{
|
||||
ResetLaraFlex(item, 12.0f);
|
||||
ResetPlayerFlex(item, 0.1f);
|
||||
}
|
||||
|
||||
// Apply and reset turn rate.
|
||||
|
@ -94,20 +94,20 @@ bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
|
||||
if (lara->Vehicle == NO_ITEM)
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
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;
|
||||
SetAnimation(item, LA_FALL_START);
|
||||
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:
|
||||
QuadBikeControl(item, coll);
|
||||
|
@ -143,7 +143,7 @@ bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
// Boats are processed like normal items in loop.
|
||||
default:
|
||||
HandleWeapon(item);
|
||||
HandleWeapon(*item);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -289,7 +289,7 @@ void DoLaraStep(ItemInfo* item, CollisionInfo* coll)
|
|||
if (TestLaraStepUp(item, coll))
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -298,7 +298,7 @@ void DoLaraStep(ItemInfo* item, CollisionInfo* coll)
|
|||
else if (TestLaraStepDown(item, coll))
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -755,29 +755,30 @@ void SetLaraVault(ItemInfo* item, CollisionInfo* coll, VaultTestResult vaultResu
|
|||
{
|
||||
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.TurnRate = 0;
|
||||
|
||||
if (vaultResult.SnapToLedge)
|
||||
{
|
||||
SnapItemToLedge(item, coll, 0.2f, false);
|
||||
lara->TargetOrientation = EulerAngles(0, coll->NearestLedgeAngle, 0);
|
||||
lara->Context.TargetOrientation = EulerAngles(0, coll->NearestLedgeAngle, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lara->TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
||||
lara->Context.TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
||||
}
|
||||
|
||||
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))
|
||||
height = -CLICK(3.5f);
|
||||
else if (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.y = 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;
|
||||
return;
|
||||
}
|
||||
|
@ -935,9 +936,9 @@ void SetLaraCornerAnimation(ItemInfo* item, CollisionInfo* coll, bool flip)
|
|||
else
|
||||
SetAnimation(item, LA_HANG_IDLE);
|
||||
|
||||
item->Pose.Position = lara->NextCornerPos.Position;
|
||||
item->Pose.Orientation.y = lara->NextCornerPos.Orientation.y;
|
||||
coll->Setup.OldPosition = lara->NextCornerPos.Position;
|
||||
item->Pose.Position = lara->Context.NextCornerPos.Position;
|
||||
item->Pose.Orientation.y = lara->Context.NextCornerPos.Orientation.y;
|
||||
coll->Setup.OldPosition = lara->Context.NextCornerPos.Position;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,98 +959,49 @@ void SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle)
|
|||
|
||||
if (vehicle == nullptr)
|
||||
{
|
||||
if (lara->Vehicle != NO_ITEM)
|
||||
g_Level.Items[lara->Vehicle].Active = false;
|
||||
if (lara->Context.Vehicle != NO_ITEM)
|
||||
g_Level.Items[lara->Context.Vehicle].Active = false;
|
||||
|
||||
lara->Vehicle = NO_ITEM;
|
||||
lara->Context.Vehicle = NO_ITEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
TENLog(std::string("ResetLaraLean() attempted division by zero!"), LogLevel::Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
rate = abs(rate);
|
||||
if (resetRoll)
|
||||
item->Pose.Orientation.Lerp(EulerAngles(item->Pose.Orientation.x, item->Pose.Orientation.y, 0), alpha);
|
||||
|
||||
if (resetPitch)
|
||||
{
|
||||
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;
|
||||
}
|
||||
item->Pose.Orientation.Lerp(EulerAngles(0, item->Pose.Orientation.y, item->Pose.Orientation.z), alpha);
|
||||
}
|
||||
|
||||
void ResetLaraFlex(ItemInfo* item, float rate)
|
||||
void ResetPlayerFlex(ItemInfo* item, float alpha)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
auto& player = GetLaraInfo(*item);
|
||||
|
||||
if (!rate)
|
||||
{
|
||||
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;
|
||||
player.ExtraHeadRot.Lerp(EulerAngles::Zero, alpha);
|
||||
player.ExtraTorsoRot.Lerp(EulerAngles::Zero, alpha);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool doPulse = (GlobalCounter & 0x0F) % 0x0F == 1;
|
||||
if (item->HitPoints == 0)
|
||||
return;
|
||||
|
||||
bool doPulse = ((GlobalCounter & 0x0F) % 0x0F == 1);
|
||||
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 SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle = nullptr);
|
||||
|
||||
void ResetLaraLean(ItemInfo* item, float rate = 1.0f, bool resetRoll = true, bool resetPitch = true);
|
||||
void ResetLaraFlex(ItemInfo* item, float rate = 1.0f);
|
||||
void ResetPlayerLean(ItemInfo* item, float alpha = 1.0f, bool resetRoll = true, bool resetPitch = true);
|
||||
void ResetPlayerFlex(ItemInfo* item, float alpha = 1.0f);
|
||||
|
||||
void RumbleLaraHealthCondition(ItemInfo* item);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#include "Game/Lara/lara_flare.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Hud;
|
||||
|
||||
void InitialiseLara(bool restore)
|
||||
void InitializeLara(bool restore)
|
||||
{
|
||||
if (Lara.ItemNumber == NO_ITEM)
|
||||
return;
|
||||
|
@ -39,10 +39,10 @@ void InitialiseLara(bool restore)
|
|||
Lara.ItemNumber = itemNumber;
|
||||
Lara.HitDirection = -1;
|
||||
Lara.Control.Weapon.WeaponItem = NO_ITEM;
|
||||
Lara.WaterSurfaceDist = 100;
|
||||
Lara.Context.WaterSurfaceDist = 100;
|
||||
|
||||
Lara.ExtraAnim = NO_ITEM;
|
||||
Lara.Vehicle = NO_ITEM;
|
||||
Lara.Context.Vehicle = NO_ITEM;
|
||||
Lara.Location = -1;
|
||||
Lara.HighestLocation = -1;
|
||||
Lara.Control.Rope.Ptr = -1;
|
||||
|
@ -50,17 +50,17 @@ void InitialiseLara(bool restore)
|
|||
Lara.Control.HandStatus = HandStatus::Free;
|
||||
|
||||
if (restore)
|
||||
InitialiseLaraLevelJump(itemNumber, &lBackup);
|
||||
InitializeLaraLevelJump(itemNumber, &lBackup);
|
||||
else
|
||||
InitialiseLaraDefaultInventory();
|
||||
InitializeLaraDefaultInventory();
|
||||
|
||||
InitialiseLaraMeshes(LaraItem);
|
||||
InitialiseLaraAnims(LaraItem);
|
||||
InitializeLaraMeshes(LaraItem);
|
||||
InitializeLaraAnims(LaraItem);
|
||||
|
||||
g_Hud.StatusBars.Initialize(*LaraItem);
|
||||
}
|
||||
|
||||
void InitialiseLaraMeshes(ItemInfo* item)
|
||||
void InitializeLaraMeshes(ItemInfo* item)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
|
||||
|
@ -126,7 +126,7 @@ void InitialiseLaraMeshes(ItemInfo* item)
|
|||
lara->RightArm.Locked = false;
|
||||
}
|
||||
|
||||
void InitialiseLaraAnims(ItemInfo* item)
|
||||
void InitializeLaraAnims(ItemInfo* item)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
|
||||
|
@ -143,13 +143,13 @@ void InitialiseLaraAnims(ItemInfo* item)
|
|||
}
|
||||
}
|
||||
|
||||
void InitialiseLaraLoad(short itemNum)
|
||||
void InitializeLaraLoad(short itemNum)
|
||||
{
|
||||
Lara.ItemNumber = 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* lara = GetLaraInfo(item);
|
||||
|
@ -169,10 +169,10 @@ void InitialiseLaraLevelJump(short itemNum, LaraInfo* lBackup)
|
|||
lara->Control.HandStatus = lBackup->Control.HandStatus;
|
||||
lara->Control.Weapon = lBackup->Control.Weapon;
|
||||
lara->Flare = lBackup->Flare;
|
||||
DrawFlareMeshes(item);
|
||||
DrawFlareMeshes(*item);
|
||||
}
|
||||
|
||||
void InitialiseLaraDefaultInventory()
|
||||
void InitializeLaraDefaultInventory()
|
||||
{
|
||||
if (Objects[ID_FLARE_INV_ITEM].loaded)
|
||||
Lara.Inventory.TotalFlares = 3;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
#include "Game/Lara/lara_struct.h"
|
||||
|
||||
void InitialiseLara(bool restore);
|
||||
void InitialiseLaraMeshes(ItemInfo* item);
|
||||
void InitialiseLaraAnims(ItemInfo* item);
|
||||
void InitialiseLaraLoad(short itemNumber);
|
||||
void InitialiseLaraLevelJump(short itemNum, LaraInfo* lBackup);
|
||||
void InitialiseLaraDefaultInventory();
|
||||
void InitializeLara(bool restore);
|
||||
void InitializeLaraMeshes(ItemInfo* item);
|
||||
void InitializeLaraAnims(ItemInfo* item);
|
||||
void InitializeLaraLoad(short itemNumber);
|
||||
void InitializeLaraLevelJump(short itemNum, LaraInfo* lBackup);
|
||||
void InitializeLaraDefaultInventory();
|
|
@ -10,11 +10,11 @@
|
|||
#include "Game/Lara/lara_basic.h"
|
||||
#include "Game/Lara/lara_overhang.h"
|
||||
#include "Game/Lara/lara_slide.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Input;
|
||||
|
||||
|
@ -126,7 +126,7 @@ void lara_col_jump_forward(ItemInfo* item, CollisionInfo* coll)
|
|||
// Collision: lara_col_freefall()
|
||||
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);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ void lara_as_pickup_flare(ItemInfo* item, CollisionInfo* coll)
|
|||
Camera.targetElevation = -ANGLE(15.0f);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -102,16 +102,14 @@ void lara_col_turn_switch(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
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->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)
|
||||
{
|
||||
SetAnimation(item, LA_TURNSWITCH_PUSH_CLOCKWISE_END);
|
||||
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.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)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
auto* pulleyItem = &g_Level.Items[lara->InteractedItem];
|
||||
auto* pulleyItem = &g_Level.Items[lara->Context.InteractedItem];
|
||||
|
||||
lara->Control.CanLook = false;
|
||||
coll->Setup.EnableSpasm = false;
|
||||
|
@ -220,7 +218,7 @@ void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
|||
item->Animation.TargetState = LS_IDLE;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -250,7 +248,7 @@ void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -284,11 +282,11 @@ void lara_as_horizontal_bar_swing(ItemInfo* item, CollisionInfo* coll)
|
|||
void lara_as_horizontal_bar_leap(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
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;
|
||||
|
||||
if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase)
|
||||
if (item->Animation.FrameNumber == GetAnimData(*item).frameBase)
|
||||
{
|
||||
int distance = 0;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
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.MaxXForward < 6750)
|
||||
{
|
||||
|
@ -690,7 +688,7 @@ void lara_col_rope_swing(ItemInfo* item, CollisionInfo* coll)
|
|||
if (TrInput & IN_JUMP)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -706,9 +704,9 @@ void lara_as_rope_up(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
#include "Game/control/control.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/clock.h"
|
||||
|
||||
enum class LaraWeaponType;
|
||||
class GameVector;
|
||||
class Pose;
|
||||
class Vector3i;
|
||||
struct ItemInfo;
|
||||
|
||||
enum class GrenadeType
|
||||
|
@ -26,28 +26,28 @@ enum class ProjectileType
|
|||
FlashGrenade
|
||||
};
|
||||
|
||||
void AnimateShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void ReadyShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void FireShotgun(ItemInfo* laraItem);
|
||||
void DrawShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void UndrawShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void DrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void UndrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void ReadyShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void FireShotgun(ItemInfo& laraItem);
|
||||
void DrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void UndrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void DrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void UndrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
|
||||
ItemInfo* FireHarpoon(ItemInfo* laraItem);
|
||||
ItemInfo* FireHarpoon(ItemInfo& laraItem);
|
||||
void HarpoonBoltControl(short itemNumber);
|
||||
void FireGrenade(ItemInfo* laraItem);
|
||||
void FireGrenade(ItemInfo& laraItem);
|
||||
void GrenadeControl(short itemNumber);
|
||||
void FireRocket(ItemInfo* laraItem);
|
||||
void FireRocket(ItemInfo& laraItem);
|
||||
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 FireCrossBowFromLaserSight(ItemInfo* laraItem, GameVector* origin, GameVector* target);
|
||||
|
||||
void FireHK(ItemInfo* laraItem, int mode);
|
||||
void RifleHandler(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void LasersightWeaponHandler(ItemInfo* item, LaraWeaponType weaponType);
|
||||
void FireHK(ItemInfo& laraItem, int mode);
|
||||
void RifleHandler(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void LasersightWeaponHandler(ItemInfo& item, LaraWeaponType weaponType);
|
||||
|
||||
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);
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
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.
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ void lara_col_slopehang(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
// Return to climbing mode.
|
||||
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.
|
||||
if (TrInput & IN_LEFT || TrInput & IN_RIGHT)
|
||||
|
@ -641,7 +641,7 @@ void lara_as_slopeclimbup(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
if (!(TrInput & IN_ACTION))
|
||||
{
|
||||
int frame = GetCurrentRelativeFrameNumber(item);
|
||||
int frame = GetFrameNumber(item);
|
||||
int length = GetFrameCount(item->Animation.AnimNumber);
|
||||
int dPos = CLICK(1) - (frame * CLICK(1) / length);
|
||||
|
||||
|
@ -671,7 +671,7 @@ void lara_as_slopeclimbdown(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
if (!(TrInput & IN_ACTION))
|
||||
{
|
||||
int frame = GetCurrentRelativeFrameNumber(item);
|
||||
int frame = GetFrameNumber(item);
|
||||
int length = GetFrameCount(item->Animation.AnimNumber);
|
||||
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.
|
||||
if (item->Animation.AnimNumber == LA_OVERHANG_MONKEY_SLOPE_CONVEX)
|
||||
{
|
||||
int frame = GetCurrentRelativeFrameNumber(item);
|
||||
int frame = GetFrameNumber(item);
|
||||
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
||||
|
||||
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.
|
||||
else if (item->Animation.AnimNumber == LA_OVERHANG_SLOPE_MONKEY_CONCAVE)
|
||||
{
|
||||
int frame = GetCurrentRelativeFrameNumber(item);
|
||||
int frame = GetFrameNumber(item);
|
||||
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
||||
|
||||
float frac = (frame * 1.25f) / (float)(numFrames);
|
||||
|
@ -810,7 +810,7 @@ void lara_as_sclimbend(ItemInfo* item, CollisionInfo* coll)
|
|||
break;
|
||||
}
|
||||
|
||||
GetLaraInfo(item)->NextCornerPos.Orientation.z = 0;
|
||||
GetLaraInfo(item)->Context.NextCornerPos.Orientation.z = 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 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;
|
||||
|
||||
|
@ -1064,7 +1064,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll)
|
|||
|
||||
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;
|
||||
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 (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) &&
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -4,14 +4,10 @@
|
|||
|
||||
using namespace TEN::Math;
|
||||
|
||||
namespace TEN::Renderer
|
||||
{
|
||||
struct RendererMesh;
|
||||
}
|
||||
|
||||
struct CreatureInfo;
|
||||
struct FX_INFO;
|
||||
struct ItemInfo;
|
||||
namespace TEN::Renderer { struct RendererMesh; };
|
||||
|
||||
// Inventory object constants
|
||||
constexpr int NUM_PUZZLES = ID_PUZZLE_ITEM16 - ID_PUZZLE_ITEM1 + 1;
|
||||
|
@ -212,6 +208,10 @@ enum LaraState
|
|||
LS_CRAWL_TURN_180 = 172,
|
||||
LS_TURN_180 = 173,
|
||||
|
||||
// 174-188 reserved for "true" ladders. -- Sezz 2023.04.16
|
||||
|
||||
LS_REMOVE_PUZZLE = 189,
|
||||
|
||||
NUM_LARA_STATES
|
||||
};
|
||||
|
||||
|
@ -508,7 +508,7 @@ enum LaraAnim
|
|||
LA_CRAWL_IDLE_TO_CRAWL_BACK = 275, // Crawl > crawl back
|
||||
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_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_END = 280, // Unused.
|
||||
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_END = 568,
|
||||
|
||||
// 569-598 reserved for "true" ladders. -- Sezz 2023.04.16
|
||||
|
||||
NUM_LARA_ANIMS
|
||||
|
||||
// TRASHED ANIMS (please reuse slots before going any higher and remove entries from this list as you go):
|
||||
// 102
|
||||
// 273, 274, 278, 280,
|
||||
// 280,
|
||||
// 343, 345,
|
||||
// 364, 366, 368, 370,
|
||||
};
|
||||
|
@ -865,6 +866,18 @@ enum 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
|
||||
{
|
||||
Ammo1,
|
||||
|
@ -893,18 +906,6 @@ enum class LaraWeaponType
|
|||
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
|
||||
{
|
||||
Empty = ID_LARA_HOLSTERS,
|
||||
|
@ -919,14 +920,6 @@ enum class HolsterSlot
|
|||
RocketLauncher = ID_ROCKET_ANIM
|
||||
};
|
||||
|
||||
// TODO: Unused.
|
||||
enum class ClothType
|
||||
{
|
||||
None,
|
||||
Dry,
|
||||
Wet
|
||||
};
|
||||
|
||||
enum class WaterStatus
|
||||
{
|
||||
Dry,
|
||||
|
@ -969,8 +962,8 @@ struct Ammo
|
|||
using CountType = int;
|
||||
|
||||
private:
|
||||
CountType Count;
|
||||
bool IsInfinite;
|
||||
CountType Count = 0;
|
||||
bool IsInfinite = false;
|
||||
|
||||
public:
|
||||
static CountType Clamp(int value)
|
||||
|
@ -988,15 +981,15 @@ public:
|
|||
return Count;
|
||||
}
|
||||
|
||||
void SetInfinite(bool infinite)
|
||||
void SetInfinite(bool isInfinite)
|
||||
{
|
||||
this->IsInfinite = infinite;
|
||||
IsInfinite = isInfinite;
|
||||
}
|
||||
|
||||
Ammo& operator --()
|
||||
{
|
||||
assertion(this->Count > 0, "Ammo count is already 0!");
|
||||
--this->Count;
|
||||
assertion(Count > 0, "Ammo count is already 0.");
|
||||
--Count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1009,7 +1002,7 @@ public:
|
|||
|
||||
Ammo& operator ++()
|
||||
{
|
||||
++this->Count;
|
||||
++Count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1015,7 @@ public:
|
|||
|
||||
Ammo& operator =(int value)
|
||||
{
|
||||
this->Count = Clamp(value);
|
||||
Count = Clamp(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1031,10 +1024,10 @@ public:
|
|||
return (Count == Clamp(value));
|
||||
}
|
||||
|
||||
Ammo& operator =(Ammo& rhs)
|
||||
Ammo& operator =(Ammo& ammo)
|
||||
{
|
||||
this->Count = rhs.Count;
|
||||
this->IsInfinite = rhs.Count;
|
||||
Count = ammo.Count;
|
||||
IsInfinite = ammo.Count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1055,20 +1048,20 @@ public:
|
|||
Ammo& operator +=(int value)
|
||||
{
|
||||
int temp = Count + value;
|
||||
this->Count = Clamp(temp);
|
||||
Count = Clamp(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ammo& operator -=(int value)
|
||||
{
|
||||
int temp = Count - value;
|
||||
this->Count = Clamp(temp);
|
||||
Count = Clamp(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return (IsInfinite || Count > 0);
|
||||
return (IsInfinite || (Count > 0));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1085,22 +1078,22 @@ struct CarriedWeaponInfo
|
|||
bool HasLasersight = false; // TODO: Duplicated in LaraInventoryData.
|
||||
bool HasSilencer = false; // TODO: Unused and duplicated in LaraInventoryData.
|
||||
|
||||
Ammo Ammo[(int)WeaponAmmoType::NumAmmoTypes] = {};
|
||||
WeaponAmmoType SelectedAmmo = WeaponAmmoType::Ammo1; // WeaponAmmoType_enum
|
||||
LaraWeaponTypeCarried WeaponMode = LaraWeaponTypeCarried::WTYPE_MISSING;
|
||||
Ammo Ammo[(int)WeaponAmmoType::NumAmmoTypes] = {};
|
||||
WeaponAmmoType SelectedAmmo = WeaponAmmoType::Ammo1; // WeaponAmmoType_enum
|
||||
LaraWeaponTypeCarried WeaponMode = LaraWeaponTypeCarried::WTYPE_MISSING;
|
||||
};
|
||||
|
||||
struct ArmInfo
|
||||
{
|
||||
int AnimNumber;
|
||||
int FrameNumber;
|
||||
int FrameBase;
|
||||
int AnimNumber = 0;
|
||||
int FrameNumber = 0;
|
||||
int FrameBase = 0;
|
||||
|
||||
EulerAngles Orientation;
|
||||
EulerAngles Orientation = EulerAngles::Zero;
|
||||
bool Locked = false;
|
||||
|
||||
bool Locked;
|
||||
int GunFlash;
|
||||
int GunSmoke;
|
||||
int GunFlash = 0;
|
||||
int GunSmoke = 0;
|
||||
};
|
||||
|
||||
struct FlareData
|
||||
|
@ -1122,29 +1115,29 @@ constexpr int MAX_DIARY_STRINGS_PER_PAGE = 8;
|
|||
|
||||
struct DiaryString
|
||||
{
|
||||
Vector2i Position;
|
||||
int StringID;
|
||||
Vector2i Position = Vector2i::Zero;
|
||||
int StringID = 0;
|
||||
};
|
||||
|
||||
struct DiaryPage
|
||||
{
|
||||
DiaryString Strings[MAX_DIARY_STRINGS_PER_PAGE];
|
||||
DiaryString Strings[MAX_DIARY_STRINGS_PER_PAGE] = {};
|
||||
};
|
||||
|
||||
struct DiaryInfo
|
||||
{
|
||||
bool Present;
|
||||
DiaryPage Pages[MAX_DIARY_PAGES];
|
||||
unsigned int NumPages;
|
||||
unsigned int CurrentPage;
|
||||
bool Present = false;
|
||||
DiaryPage Pages[MAX_DIARY_PAGES] = {};
|
||||
unsigned int NumPages = 0;
|
||||
unsigned int CurrentPage = 0;
|
||||
};
|
||||
|
||||
struct LaraInventoryData
|
||||
{
|
||||
bool IsBusy;
|
||||
bool OldBusy;
|
||||
bool IsBusy = false;
|
||||
bool OldBusy = false;
|
||||
|
||||
DiaryInfo Diary;
|
||||
DiaryInfo Diary = {};
|
||||
|
||||
byte BeetleLife;
|
||||
int BeetleComponents; // BeetleComponentFlags enum
|
||||
|
@ -1157,29 +1150,29 @@ struct LaraInventoryData
|
|||
int TotalFlares;
|
||||
unsigned int TotalSecrets;
|
||||
|
||||
bool HasBinoculars;
|
||||
bool HasCrowbar;
|
||||
bool HasTorch;
|
||||
bool HasLasersight;
|
||||
bool HasSilencer; // TODO: Unused.
|
||||
bool HasBinoculars = false;
|
||||
bool HasCrowbar = false;
|
||||
bool HasTorch = false;
|
||||
bool HasLasersight = false;
|
||||
bool HasSilencer = false; // TODO: Unused.
|
||||
|
||||
// TODO: Convert to bools.
|
||||
int Puzzles[NUM_PUZZLES];
|
||||
int Keys[NUM_KEYS];
|
||||
int Pickups[NUM_PICKUPS];
|
||||
int Examines[NUM_EXAMINES];
|
||||
int PuzzlesCombo[NUM_PUZZLES * 2];
|
||||
int KeysCombo[NUM_KEYS * 2];
|
||||
int PickupsCombo[NUM_PICKUPS * 2];
|
||||
int ExaminesCombo[NUM_EXAMINES * 2];
|
||||
int Puzzles[NUM_PUZZLES] = {};
|
||||
int Keys[NUM_KEYS] = {};
|
||||
int Pickups[NUM_PICKUPS] = {};
|
||||
int Examines[NUM_EXAMINES] = {};
|
||||
int PuzzlesCombo[NUM_PUZZLES * 2] = {};
|
||||
int KeysCombo[NUM_KEYS * 2] = {};
|
||||
int PickupsCombo[NUM_PICKUPS * 2] = {};
|
||||
int ExaminesCombo[NUM_EXAMINES * 2] = {};
|
||||
};
|
||||
|
||||
struct LaraCountData
|
||||
{
|
||||
unsigned int Pose;
|
||||
unsigned int PositionAdjust;
|
||||
unsigned int Run;
|
||||
unsigned int Death;
|
||||
unsigned int Pose = 0;
|
||||
unsigned int PositionAdjust = 0;
|
||||
unsigned int Run = 0;
|
||||
unsigned int Death = 0;
|
||||
};
|
||||
|
||||
struct WeaponControlData
|
||||
|
@ -1204,31 +1197,37 @@ struct WeaponControlData
|
|||
|
||||
struct RopeControlData
|
||||
{
|
||||
byte Segment;
|
||||
byte Direction;
|
||||
short ArcFront;
|
||||
short ArcBack;
|
||||
short LastX;
|
||||
short MaxXForward;
|
||||
short MaxXBackward;
|
||||
int DFrame;
|
||||
int Frame;
|
||||
unsigned short FrameRate;
|
||||
unsigned short Y;
|
||||
int Ptr;
|
||||
int Offset;
|
||||
int DownVel;
|
||||
byte Flag;
|
||||
int Count;
|
||||
byte Segment = 0;
|
||||
byte Direction = 0;
|
||||
|
||||
short ArcFront = 0;
|
||||
short ArcBack = 0;
|
||||
|
||||
short LastX = 0;
|
||||
short MaxXForward = 0;
|
||||
short MaxXBackward = 0;
|
||||
|
||||
int DFrame = 0;
|
||||
int Frame = 0;
|
||||
unsigned short FrameRate = 0;
|
||||
|
||||
unsigned short Y = 0;
|
||||
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
|
||||
{
|
||||
#if NEW_TIGHTROPE
|
||||
float Balance;
|
||||
unsigned int TimeOnTightrope;
|
||||
bool CanDismount;
|
||||
short TightropeItem; // TODO: Give tightrope a property for difficulty?
|
||||
short TightropeItem = 0;
|
||||
bool CanDismount = false;
|
||||
float Balance = 0.0f;
|
||||
unsigned int TimeOnTightrope = 0;
|
||||
#else // !NEW_TIGHTROPE
|
||||
unsigned int OnCount;
|
||||
byte Off;
|
||||
|
@ -1238,25 +1237,24 @@ struct TightropeControlData
|
|||
|
||||
struct SubsuitControlData
|
||||
{
|
||||
short XRot;
|
||||
short DXRot;
|
||||
int Velocity[2];
|
||||
int VerticalVelocity;
|
||||
short XRot = 0;
|
||||
short DXRot = 0;
|
||||
int Velocity[2] = {};
|
||||
int VerticalVelocity = 0;
|
||||
|
||||
// TODO: These appear to be unused.
|
||||
short XRotVel;
|
||||
unsigned short HitCount;
|
||||
short XRotVel = 0;
|
||||
unsigned short HitCount = 0;
|
||||
};
|
||||
|
||||
struct LaraControlData
|
||||
{
|
||||
short MoveAngle = 0;
|
||||
short TurnRate = 0;
|
||||
int CalculatedJumpVelocity = 0;
|
||||
|
||||
JumpDirection JumpDirection = {};
|
||||
HandStatus HandStatus = {};
|
||||
WaterStatus WaterStatus = {};
|
||||
JumpDirection JumpDirection = {};
|
||||
LaraCountData Count = {};
|
||||
|
||||
RopeControlData Rope = {};
|
||||
|
@ -1265,25 +1263,19 @@ struct LaraControlData
|
|||
WeaponControlData Weapon = {};
|
||||
|
||||
bool IsClimbingLadder = false;
|
||||
bool Locked = false;
|
||||
bool Locked = false; // IsLocked
|
||||
bool IsLow = false;
|
||||
bool IsMonkeySwinging = false;
|
||||
bool IsMoving = false;
|
||||
bool RunJumpQueued = false;
|
||||
bool KeepLow = false;
|
||||
bool RunJumpQueued = false; // IsRunJumpQueued
|
||||
bool KeepLow = false; // IsInLowSpace
|
||||
|
||||
bool CanClimbLadder = false;
|
||||
bool CanLook = false;
|
||||
bool CanMonkeySwing = false;
|
||||
};
|
||||
|
||||
struct PlayerEffectData
|
||||
{
|
||||
std::array<float, NUM_LARA_MESHES> DripNodes = {};
|
||||
std::array<float, NUM_LARA_MESHES> BubbleNodes = {};
|
||||
};
|
||||
|
||||
// TODO: Make these floats.
|
||||
// TODO: Refactor status handling to use floats.
|
||||
struct PlayerStatusData
|
||||
{
|
||||
int Air = 0;
|
||||
|
@ -1292,40 +1284,54 @@ struct PlayerStatusData
|
|||
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
|
||||
{
|
||||
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 = {};
|
||||
LaraInventoryData Inventory;
|
||||
CarriedWeaponInfo Weapons[(int)LaraWeaponType::NumWeapons];
|
||||
FlareData Flare = {};
|
||||
TorchData Torch = {};
|
||||
LaraControlData Control = {};
|
||||
PlayerContextData Context = {};
|
||||
PlayerStatusData Status = {};
|
||||
PlayerEffectData Effect = {};
|
||||
LaraInventoryData Inventory = {};
|
||||
|
||||
EulerAngles ExtraHeadRot = {};
|
||||
EulerAngles ExtraTorsoRot = {};
|
||||
short WaterCurrentActive = 0;
|
||||
Vector3i WaterCurrentPull = Vector3i::Zero;
|
||||
FlareData Flare = {};
|
||||
TorchData Torch = {};
|
||||
CarriedWeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] = {};
|
||||
|
||||
EulerAngles ExtraHeadRot = {};
|
||||
EulerAngles ExtraTorsoRot = {};
|
||||
ArmInfo LeftArm = {};
|
||||
ArmInfo RightArm = {};
|
||||
EulerAngles TargetArmOrient = EulerAngles::Zero;
|
||||
ItemInfo* TargetEntity = nullptr;
|
||||
ItemInfo* TargetEntity = nullptr; // TargetEntityPtr. Should use item number instead?
|
||||
|
||||
int Vehicle;
|
||||
int ExtraAnim;
|
||||
int HitFrame;
|
||||
int HitDirection;
|
||||
FX_INFO* SpasmEffect; // Not saved. TODO: Restore this effect.
|
||||
// TODO: Rewrite and restore spasm effect. Also move to PlayerEffectData?
|
||||
int HitFrame = 0; // Frame index.
|
||||
int HitDirection = 0; // Cardinal direction.
|
||||
FX_INFO* SpasmEffect = nullptr; // Not saved.
|
||||
|
||||
short InteractedItem;
|
||||
int ProjectedFloorHeight;
|
||||
EulerAngles TargetOrientation;
|
||||
int WaterSurfaceDist;
|
||||
Pose NextCornerPos;
|
||||
|
||||
PlayerEffectData Effect = {};
|
||||
int ExtraAnim = 0; // Item number? Only ever set to NO_ITEM or 1.
|
||||
|
||||
signed char Location = 0;
|
||||
signed char HighestLocation = 0;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
using namespace TEN::Input;
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Renderer;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using std::vector;
|
||||
|
||||
// -----------------------------
|
||||
|
@ -170,7 +170,7 @@ bool TestLaraHang(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
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))
|
||||
{
|
||||
item->Animation.TargetState = LS_LADDER_IDLE;
|
||||
|
@ -273,7 +273,7 @@ bool TestLaraHangJump(ItemInfo* item, CollisionInfo* coll)
|
|||
if (TestLaraMonkeyGrab(item, coll))
|
||||
{
|
||||
SetAnimation(item, LA_REACH_TO_MONKEY);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.z = 0;
|
||||
item->Animation.Velocity.y = 0;
|
||||
item->Animation.IsAirborne = false;
|
||||
|
@ -300,7 +300,7 @@ bool TestLaraHangJump(ItemInfo* item, CollisionInfo* coll)
|
|||
if (TestHangSwingIn(item, coll))
|
||||
{
|
||||
SetAnimation(item, LA_REACH_TO_HANG_OSCILLATE);
|
||||
ResetLaraFlex(item);
|
||||
ResetPlayerFlex(item);
|
||||
}
|
||||
else
|
||||
SetAnimation(item, LA_REACH_TO_HANG);
|
||||
|
@ -575,12 +575,12 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
|||
|
||||
// Store next position
|
||||
item->Pose = cornerResult.RealPositionResult;
|
||||
lara->NextCornerPos.Position = Vector3i(
|
||||
lara->Context.NextCornerPos.Position = Vector3i(
|
||||
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),
|
||||
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;
|
||||
|
||||
item->Pose = cornerResult.ProbeResult;
|
||||
|
@ -596,9 +596,9 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
|||
if (lara->Control.CanClimbLadder)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -634,10 +634,10 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
|||
|
||||
// Store next position
|
||||
item->Pose = cornerResult.RealPositionResult;
|
||||
lara->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->NextCornerPos.Position.z = item->Pose.Position.z;
|
||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
||||
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x;
|
||||
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->Context.NextCornerPos.Position.z = item->Pose.Position.z;
|
||||
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
||||
lara->Control.MoveAngle = item->Pose.Orientation.y;
|
||||
|
||||
item->Pose = cornerResult.ProbeResult;
|
||||
|
@ -653,9 +653,9 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
|||
if (lara->Control.CanClimbLadder)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ bool TestLaraPose(ItemInfo* item, CollisionInfo* coll)
|
|||
lara->Control.HandStatus == HandStatus::Free && // Hands are free.
|
||||
(lara->Control.Weapon.GunType != LaraWeaponType::Flare || // Flare is not being handled.
|
||||
lara->Flare.Life) &&
|
||||
lara->Vehicle == NO_ITEM) // Not in a vehicle.
|
||||
lara->Context.Vehicle == NO_ITEM) // Not in a vehicle.
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1645,7 +1645,7 @@ bool TestLaraCrouchRoll(ItemInfo* item, CollisionInfo* coll)
|
|||
auto* lara = GetLaraInfo(item);
|
||||
|
||||
// Assess water depth.
|
||||
if (lara->WaterSurfaceDist < -CLICK(1))
|
||||
if (lara->Context.WaterSurfaceDist < -CLICK(1))
|
||||
return false;
|
||||
|
||||
// Assess continuity of path.
|
||||
|
@ -1830,7 +1830,7 @@ VaultTestResult TestLaraVaultTolerance(ItemInfo* item, CollisionInfo* coll, Vaul
|
|||
auto probeMiddle = GetCollision(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
|
||||
|
||||
// Check swamp depth (if applicable).
|
||||
|
@ -2065,7 +2065,7 @@ VaultTestResult TestLaraVault(ItemInfo* item, CollisionInfo* coll)
|
|||
if (!(TrInput & IN_ACTION) || lara->Control.HandStatus != HandStatus::Free)
|
||||
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 };
|
||||
|
||||
VaultTestResult vaultResult;
|
||||
|
@ -2154,24 +2154,24 @@ bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll)
|
|||
if (!(TrInput & IN_ACTION) || !(TrInput & IN_FORWARD) || lara->Control.HandStatus != HandStatus::Free)
|
||||
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;
|
||||
|
||||
// Auto jump to ladder.
|
||||
auto vaultResult = TestLaraLadderAutoJump(item, coll);
|
||||
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.
|
||||
lara->Control.CalculatedJumpVelocity = -3 - sqrt(-9600 - 12 * std::max((vaultResult.Height - item->Pose.Position.y + CLICK(0.2f)), -CLICK(7.1f)));
|
||||
// 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->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.FrameNumber = GetFrameNumber(item, 0);
|
||||
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||
item->Animation.TargetState = LS_JUMP_UP;
|
||||
item->Animation.ActiveState = LS_IDLE;
|
||||
lara->Control.TurnRate = 0;
|
||||
|
||||
ShiftItem(item, coll);
|
||||
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);
|
||||
|
||||
return true;
|
||||
|
@ -2183,7 +2183,7 @@ bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll)
|
|||
TestLaraClimbIdle(item, coll))
|
||||
{
|
||||
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.ActiveState = LS_IDLE;
|
||||
lara->Control.HandStatus = HandStatus::Busy;
|
||||
|
|
|
@ -9,504 +9,417 @@
|
|||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_fire.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Lara/lara_struct.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 "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
using namespace TEN::Input;
|
||||
using namespace TEN::Math::Random;
|
||||
using namespace TEN::Math;
|
||||
|
||||
struct PistolDef
|
||||
struct WeaponAnimData
|
||||
{
|
||||
short ObjectNumber;
|
||||
int Draw1Anim2;
|
||||
int Draw1Anim;
|
||||
int Draw2Anim;
|
||||
int RecoilAnim;
|
||||
GAME_OBJECT_ID ObjectID = GAME_OBJECT_ID::ID_NO_OBJECT;
|
||||
|
||||
int Draw1Anim2 = 0;
|
||||
int Draw1Anim = 0;
|
||||
int Draw2Anim = 0;
|
||||
int RecoilAnim = 0;
|
||||
};
|
||||
|
||||
PistolDef PistolsTable[4] =
|
||||
static WeaponAnimData GetWeaponAnimData(LaraWeaponType weaponType)
|
||||
{
|
||||
{ ID_LARA, 0, 0, 0, 0 },
|
||||
{ ID_PISTOLS_ANIM, 4, 5, 13, 24 },
|
||||
{ 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())
|
||||
static const auto DEFAULT_WEAPON_ANIM_DATA = WeaponAnimData{ ID_LARA, 0, 0, 0, 0 };
|
||||
static const auto ANIM_DATA_MAP = std::unordered_map<LaraWeaponType, WeaponAnimData>
|
||||
{
|
||||
if (lara->LeftArm.GunSmoke)
|
||||
{
|
||||
auto offset = Vector3i::Zero;
|
||||
switch (weaponType)
|
||||
{
|
||||
case LaraWeaponType::Pistol:
|
||||
offset = Vector3i(4, 128, 40);
|
||||
break;
|
||||
{ LaraWeaponType::None, WeaponAnimData{ ID_LARA, 0, 0, 0, 0 } },
|
||||
{ LaraWeaponType::Pistol, WeaponAnimData{ ID_PISTOLS_ANIM, 4, 5, 13, 24 } },
|
||||
{ LaraWeaponType::Revolver, WeaponAnimData{ ID_REVOLVER_ANIM , 7, 8, 15, 29 } },
|
||||
{ LaraWeaponType::Uzi, WeaponAnimData{ ID_UZI_ANIM, 4, 5, 13, 24 } }
|
||||
};
|
||||
|
||||
case LaraWeaponType::Revolver:
|
||||
offset = Vector3i(16, 160, 56);
|
||||
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);
|
||||
auto it = ANIM_DATA_MAP.find(weaponType);
|
||||
return ((it != ANIM_DATA_MAP.end()) ? it->second : DEFAULT_WEAPON_ANIM_DATA);
|
||||
}
|
||||
|
||||
void PistolHandler(ItemInfo* laraItem, LaraWeaponType weaponType)
|
||||
static Vector3i GetWeaponSmokeRelOffset(LaraWeaponType weaponType, bool isRightWeapon)
|
||||
{
|
||||
auto* lara = GetLaraInfo(laraItem);
|
||||
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)
|
||||
switch (weaponType)
|
||||
{
|
||||
lara->ExtraTorsoRot.x = lara->LeftArm.Orientation.x / 2;
|
||||
lara->ExtraTorsoRot.y = lara->LeftArm.Orientation.y / 2;
|
||||
case LaraWeaponType::Pistol:
|
||||
return Vector3i(isRightWeapon ? -16 : 4, 128, 40);
|
||||
|
||||
if (Camera.oldType != CameraType::Look)
|
||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
||||
}
|
||||
else if (!lara->LeftArm.Locked && lara->RightArm.Locked)
|
||||
{
|
||||
lara->ExtraTorsoRot.x = lara->RightArm.Orientation.x / 2;
|
||||
lara->ExtraTorsoRot.y = lara->RightArm.Orientation.y / 2;
|
||||
case LaraWeaponType::Revolver:
|
||||
return Vector3i(isRightWeapon ? -32 : 16, 160, 56);
|
||||
|
||||
if (Camera.oldType != CameraType::Look)
|
||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
||||
}
|
||||
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;
|
||||
case LaraWeaponType::Uzi:
|
||||
return Vector3i(isRightWeapon ? -16 : 8, 140, 48);
|
||||
|
||||
if (Camera.oldType != CameraType::Look)
|
||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
||||
}
|
||||
|
||||
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);
|
||||
default:
|
||||
return Vector3i::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
int animBase = Objects[(int)weaponAnimData.ObjectID].animIndex;
|
||||
|
||||
void DrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType)
|
||||
{
|
||||
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)
|
||||
if (frame < weaponAnimData.Draw1Anim)
|
||||
{
|
||||
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;
|
||||
else if (frame < pistols.Draw2Anim)
|
||||
}
|
||||
else if (frame < weaponAnimData.Draw2Anim)
|
||||
{
|
||||
arm.AnimNumber = animBase + 1;
|
||||
else if (frame < pistols.RecoilAnim)
|
||||
}
|
||||
else if (frame < weaponAnimData.RecoilAnim)
|
||||
{
|
||||
arm.AnimNumber = animBase + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
arm.AnimNumber = animBase + 3;
|
||||
}
|
||||
|
||||
arm.FrameNumber = frame;
|
||||
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)
|
||||
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
||||
|
||||
lara->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;
|
||||
player.Control.HandStatus = HandStatus::WeaponReady;
|
||||
player.TargetEntity = nullptr;
|
||||
player.LeftArm.FrameBase =
|
||||
player.RightArm.FrameBase = Objects[GetWeaponObjectID(weaponType)].frameBase;
|
||||
player.LeftArm.FrameNumber =
|
||||
player.RightArm.FrameNumber = 0;
|
||||
player.LeftArm.Orientation =
|
||||
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;
|
||||
if (lara->Weapons[(int)weaponType].Present)
|
||||
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)
|
||||
// Spawn weapon smoke.
|
||||
if (laraItem.MeshBits.TestAny() && arm.GunSmoke)
|
||||
{
|
||||
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)
|
||||
lara->Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(weaponType);
|
||||
else
|
||||
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
||||
int frame = arm.FrameNumber;
|
||||
|
||||
// Wind animation forward.
|
||||
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
|
||||
#include "Game/Lara/lara_struct.h"
|
||||
|
||||
void AnimatePistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void PistolHandler(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void ReadyPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void DrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void UndrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void SetArmInfo(ItemInfo* laraItem, ArmInfo& arm, int frame);
|
||||
void DrawPistolMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void UndrawPistolMeshRight(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
void UndrawPistolMeshLeft(ItemInfo* laraItem, LaraWeaponType weaponType);
|
||||
enum class LaraWeaponType;
|
||||
struct ItemInfo;
|
||||
|
||||
void HandlePistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void AnimatePistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
|
||||
void DrawPistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||
void DrawPistolMeshes(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
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Game/control/box.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer11Enums.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
enum class ZoneType;
|
||||
struct CollisionInfo;
|
||||
struct ItemInfo;
|
||||
|
||||
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
|
||||
{
|
||||
Skeleton,
|
||||
|
@ -23,7 +23,8 @@ enum class LotType
|
|||
Flyer,
|
||||
Blockable, // For large creatures such as trex and shiva.
|
||||
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
|
||||
|
@ -52,53 +53,59 @@ enum ShatterType
|
|||
|
||||
struct ObjectInfo
|
||||
{
|
||||
int nmeshes;
|
||||
int meshIndex;
|
||||
int boneIndex;
|
||||
int frameBase;
|
||||
bool loaded = false; // IsLoaded
|
||||
|
||||
int nmeshes; // BoneCount
|
||||
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;
|
||||
int animIndex;
|
||||
short HitPoints;
|
||||
short pivotLength;
|
||||
short radius;
|
||||
ShadowMode shadowType;
|
||||
short biteOffset;
|
||||
bool loaded;
|
||||
bool intelligent;
|
||||
bool nonLot;
|
||||
bool waterCreature;
|
||||
bool usingDrawAnimatingItem;
|
||||
HitEffect hitEffect;
|
||||
bool undead;
|
||||
bool isPickup;
|
||||
bool isPuzzleHole;
|
||||
ShadowMode shadowType;
|
||||
|
||||
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;
|
||||
|
||||
std::function<void(short itemNumber)> initialise;
|
||||
std::function<void(short itemNumber)> control;
|
||||
std::function<void(short itemNumber)> Initialize;
|
||||
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)> ceiling;
|
||||
std::function<int(short itemNumber)> floorBorder;
|
||||
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;
|
||||
std::function<int(short itemNumber)> floorBorder;
|
||||
std::function<int(short itemNumber)> ceilingBorder;
|
||||
|
||||
/// <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>
|
||||
/// <param name="boneID">the mesh id - 1</param>
|
||||
/// <param name="flags">can be ROT_X, ROT_Y, ROT_Z or all.</param>
|
||||
void SetBoneRotationFlags(int boneID, int flags)
|
||||
/// <param name="boneNumber:">Mesh number - 1.</param>
|
||||
/// <param name="flags:">JointRotationFlags enum.</param>
|
||||
void SetBoneRotationFlags(int boneNumber, int flags)
|
||||
{
|
||||
g_Level.Bones[boneIndex + boneID * 4] |= flags;
|
||||
g_Level.Bones[boneIndex + (boneNumber * 4)] |= flags;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <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)
|
||||
{
|
||||
// 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 STATIC_INFO StaticObjects[MAX_STATICS];
|
||||
|
||||
void InitialiseGameFlags();
|
||||
void InitialiseSpecialEffects();
|
||||
void InitialiseObjects();
|
||||
void InitializeGameFlags();
|
||||
void InitializeSpecialEffects();
|
||||
void InitializeObjects();
|
|
@ -8,12 +8,12 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Generic/Object/rope.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Math;
|
||||
|
@ -74,10 +74,10 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased)
|
|||
{
|
||||
auto& player = GetLaraInfo(item);
|
||||
|
||||
if (player.Control.CalculatedJumpVelocity != 0)
|
||||
if (player.Context.CalcJumpVelocity != 0)
|
||||
{
|
||||
item.Animation.Velocity.y = player.Control.CalculatedJumpVelocity;
|
||||
player.Control.CalculatedJumpVelocity = 0;
|
||||
item.Animation.Velocity.y = player.Context.CalcJumpVelocity;
|
||||
player.Context.CalcJumpVelocity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +121,8 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased)
|
|||
auto& player = GetLaraInfo(item);
|
||||
|
||||
if (playAlways ||
|
||||
(playOnLand && (player.WaterSurfaceDist >= -SHALLOW_WATER_DEPTH || player.WaterSurfaceDist == NO_HEIGHT)) ||
|
||||
(playInWater && player.WaterSurfaceDist < -SHALLOW_WATER_DEPTH && player.WaterSurfaceDist != NO_HEIGHT && !TestEnvironment(ENV_FLAG_SWAMP, &item)))
|
||||
(playOnLand && (player.Context.WaterSurfaceDist >= -SHALLOW_WATER_DEPTH || player.Context.WaterSurfaceDist == NO_HEIGHT)) ||
|
||||
(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);
|
||||
}
|
||||
|
@ -216,6 +216,19 @@ void AnimateItem(ItemInfo* item)
|
|||
{
|
||||
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);
|
||||
|
@ -336,19 +349,23 @@ bool HasStateDispatch(ItemInfo* item, int targetState)
|
|||
|
||||
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));
|
||||
}
|
||||
|
||||
bool TestLastFrame(ItemInfo* item, int animNumber)
|
||||
{
|
||||
if (animNumber == NO_ANIM)
|
||||
animNumber = item->Animation.AnimNumber;
|
||||
const auto& object = Objects[item->Animation.AnimObjectID];
|
||||
|
||||
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;
|
||||
|
||||
const auto& anim = GetAnimData(*item, animNumber);
|
||||
const auto& anim = GetAnimData(object, animNumber);
|
||||
return (item->Animation.FrameNumber >= anim.frameEnd);
|
||||
}
|
||||
|
||||
|
@ -380,32 +397,49 @@ void TranslateItem(ItemInfo* item, const Vector3& direction, float 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];
|
||||
int animIndex = object.animIndex + animNumber;
|
||||
const auto& animObject = Objects[animObjectID];
|
||||
int animIndex = animObject.animIndex + animNumber;
|
||||
|
||||
// Animation already set; return early.
|
||||
if (item->Animation.AnimNumber == animIndex)
|
||||
return;
|
||||
|
||||
// Animation doesn't exist; return early.
|
||||
// Animation is missing; return early.
|
||||
if (animIndex < 0 || animIndex >= g_Level.Anims.size())
|
||||
{
|
||||
TENLog(
|
||||
std::string("Attempted to set nonexistent animation ") + std::to_string(animNumber) +
|
||||
std::string(" for object ") + std::to_string(item->ObjectNumber),
|
||||
std::string("Attempted to set missing animation ") + std::to_string(animNumber) +
|
||||
(animObjectID == item.ObjectNumber ? std::string() : std::string(" from object ") + GetObjectName(animObjectID)) +
|
||||
std::string(" for object ") + GetObjectName(item.ObjectNumber),
|
||||
LogLevel::Warning);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& anim = GetAnimData(*item, animNumber);
|
||||
|
||||
item->Animation.AnimNumber = animIndex;
|
||||
item->Animation.FrameNumber = anim.frameBase + frameNumber;
|
||||
item->Animation.ActiveState =
|
||||
item->Animation.TargetState = anim.ActiveState;
|
||||
const auto& anim = GetAnimData(animObject, animNumber);
|
||||
int frameIndex = anim.frameBase + frameNumber;
|
||||
|
||||
// Animation already set; return early.
|
||||
if (item.Animation.AnimObjectID == animObjectID &&
|
||||
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)
|
||||
|
@ -413,6 +447,12 @@ AnimData& GetAnimData(int 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// Active and target states already match; return early.
|
||||
|
@ -464,123 +632,6 @@ bool GetStateDispatch(ItemInfo* item, const AnimData& anim)
|
|||
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)
|
||||
{
|
||||
// TODO: to refactor
|
||||
|
@ -613,6 +664,16 @@ Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOff
|
|||
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)
|
||||
{
|
||||
const auto& object = Objects[objectID];
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
|
||||
using namespace TEN::Math;
|
||||
|
||||
enum GAME_OBJECT_ID : short;
|
||||
class EulerAngles;
|
||||
class Pose;
|
||||
class Vector3i;
|
||||
struct CreatureBiteInfo;
|
||||
struct ItemInfo;
|
||||
struct ObjectInfo;
|
||||
|
||||
// NOTES:
|
||||
// animNumber: Relative entity animation ID.
|
||||
// animNumber: Relative animation number.
|
||||
// animIndex: Index of animation in giant g_Level.Anims vector.
|
||||
|
||||
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);
|
||||
|
||||
// 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
|
||||
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 ItemInfo& item, int animNumber = NO_ANIM);
|
||||
int GetCurrentRelativeFrameNumber(ItemInfo* item);
|
||||
int GetAnimNumber(ItemInfo& item, int animNumber);
|
||||
int GetFrameNumber(ItemInfo* item, int frameToStart);
|
||||
int GetFrameNumber(int objectID, int animNumber, int frameToStart);
|
||||
int GetFrameCount(int animIndex);
|
||||
int GetNextAnimState(ItemInfo* item);
|
||||
int GetNextAnimState(int objectID, int animNumber);
|
||||
bool GetStateDispatch(ItemInfo* item, const AnimData& anim);
|
||||
|
||||
int GetAnimNumber(const ItemInfo& item);
|
||||
int GetAnimIndex(const ItemInfo& item, int animNumber);
|
||||
|
||||
int GetFrameNumber(const ItemInfo& item);
|
||||
int GetFrameNumber(ItemInfo* item); // Deprecated.
|
||||
int GetFrameIndex(ItemInfo* item, int frameNumber);
|
||||
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);
|
||||
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(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);
|
||||
Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex);
|
||||
float GetBoneLength(GAME_OBJECT_ID objectID, int boneIndex);
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Game/spotcam.h"
|
||||
#include "Objects/Generic/Object/burning_torch.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using TEN::Renderer::g_Renderer;
|
||||
|
||||
|
@ -117,7 +117,7 @@ inline void RumbleFromBounce()
|
|||
}
|
||||
|
||||
|
||||
void InitialiseCamera()
|
||||
void InitializeCamera()
|
||||
{
|
||||
Camera.shift = LaraItem->Pose.Position.y - SECTOR(1);
|
||||
|
||||
|
@ -545,8 +545,11 @@ void DoThumbstickCamera()
|
|||
Camera.target.y == OldCam.target.y &&
|
||||
Camera.target.z == OldCam.target.z))
|
||||
{
|
||||
Camera.targetAngle = ANGLE(THUMBCAM_VERTICAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraHorizontal]);
|
||||
Camera.targetElevation = ANGLE(-10.0f + (THUMBCAM_HORIZONTAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraVertical]));
|
||||
if (abs(AxisMap[InputAxis::CameraHorizontal]) > EPSILON && abs(Camera.targetAngle) == 0)
|
||||
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 &&
|
||||
lara->Vehicle == NO_ITEM &&
|
||||
lara->Context.Vehicle == NO_ITEM &&
|
||||
!lara->LeftArm.Locked &&
|
||||
!lara->RightArm.Locked)
|
||||
{
|
||||
|
@ -1602,7 +1605,7 @@ void LookUpDown(ItemInfo* item)
|
|||
}
|
||||
|
||||
if (lara->Control.HandStatus != HandStatus::Busy &&
|
||||
lara->Vehicle == NO_ITEM &&
|
||||
lara->Context.Vehicle == NO_ITEM &&
|
||||
!lara->LeftArm.Locked &&
|
||||
!lara->RightArm.Locked)
|
||||
{
|
||||
|
@ -1634,7 +1637,7 @@ void ResetLook(ItemInfo* item)
|
|||
if (lara->Control.HandStatus != HandStatus::Busy &&
|
||||
!lara->LeftArm.Locked &&
|
||||
!lara->RightArm.Locked &&
|
||||
lara->Vehicle == NO_ITEM)
|
||||
lara->Context.Vehicle == NO_ITEM)
|
||||
{
|
||||
lara->ExtraTorsoRot = lara->ExtraHeadRot;
|
||||
}
|
||||
|
@ -2074,7 +2077,7 @@ void HandleOptics(ItemInfo* item)
|
|||
AlterFOV(LastFOV);
|
||||
|
||||
Lara.Inventory.IsBusy = false;
|
||||
ResetLaraFlex(LaraItem);
|
||||
ResetPlayerFlex(LaraItem);
|
||||
|
||||
TrInput &= ~IN_LOOK;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ extern float CinematicBarsSpeed;
|
|||
void LookAt(CAMERA_INFO* cam, short roll);
|
||||
void AlterFOV(short value, bool store = true);
|
||||
short GetCurrentFOV();
|
||||
void InitialiseCamera();
|
||||
void InitializeCamera();
|
||||
void MoveCamera(GameVector* ideal, int speed);
|
||||
void ChaseCamera(ItemInfo* item);
|
||||
void UpdateCameraElevation();
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/pickup/pickup.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "ScriptInterfaceGame.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Renderer;
|
||||
|
@ -51,6 +51,7 @@ void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionIn
|
|||
|
||||
if (item->ItemFlags[2] != 0)
|
||||
collidedBits &= ~1;
|
||||
coll->Setup.EnableObjectPush = item->ItemFlags[4] == 0;
|
||||
|
||||
while (collidedBits)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "Sound/sound.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Renderer;
|
||||
|
||||
|
@ -239,7 +239,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
int xFront, zFront, xRight, zRight, xLeft, zLeft;
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
else
|
||||
{
|
||||
height = GetCollision(probePos.x + xFront, probePos.y, probePos.z + zFront, topRoomNumber).Position.Floor;
|
||||
}
|
||||
|
||||
if (height != NO_HEIGHT)
|
||||
height -= (doPlayerCollision ? entityPos.y : probePos.y);
|
||||
|
@ -408,19 +410,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
coll->Front.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||
coll->Front.FloorSlope &&
|
||||
coll->Front.Floor > coll->Middle.Floor)
|
||||
coll->Front.FloorSlope &&
|
||||
coll->Front.Floor > coll->Middle.Floor)
|
||||
{
|
||||
coll->Front.Floor = STOP_SIZE;
|
||||
}
|
||||
else if (coll->Setup.BlockCeilingSlope &&
|
||||
coll->Front.CeilingSlope)
|
||||
coll->Front.CeilingSlope)
|
||||
{
|
||||
coll->Front.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockDeathFloorDown &&
|
||||
coll->Front.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
coll->Front.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
{
|
||||
coll->Front.Floor = STOP_SIZE;
|
||||
}
|
||||
|
@ -471,19 +473,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||
coll->MiddleLeft.FloorSlope &&
|
||||
coll->MiddleLeft.Floor > 0)
|
||||
coll->MiddleLeft.FloorSlope &&
|
||||
coll->MiddleLeft.Floor > 0)
|
||||
{
|
||||
coll->MiddleLeft.Floor = STOP_SIZE;
|
||||
}
|
||||
else if (coll->Setup.BlockCeilingSlope &&
|
||||
coll->MiddleLeft.CeilingSlope)
|
||||
coll->MiddleLeft.CeilingSlope)
|
||||
{
|
||||
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockDeathFloorDown &&
|
||||
coll->MiddleLeft.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
coll->MiddleLeft.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
{
|
||||
coll->MiddleLeft.Floor = STOP_SIZE;
|
||||
}
|
||||
|
@ -528,19 +530,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
coll->FrontLeft.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||
coll->FrontLeft.FloorSlope &&
|
||||
coll->FrontLeft.Floor > 0)
|
||||
coll->FrontLeft.FloorSlope &&
|
||||
coll->FrontLeft.Floor > 0)
|
||||
{
|
||||
coll->FrontLeft.Floor = STOP_SIZE;
|
||||
}
|
||||
else if (coll->Setup.BlockCeilingSlope &&
|
||||
coll->FrontLeft.CeilingSlope)
|
||||
coll->FrontLeft.CeilingSlope)
|
||||
{
|
||||
coll->FrontLeft.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockDeathFloorDown &&
|
||||
coll->FrontLeft.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
coll->FrontLeft.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
{
|
||||
coll->FrontLeft.Floor = STOP_SIZE;
|
||||
}
|
||||
|
@ -590,19 +592,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
coll->MiddleRight.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||
coll->MiddleRight.FloorSlope &&
|
||||
coll->MiddleRight.Floor > 0)
|
||||
coll->MiddleRight.FloorSlope &&
|
||||
coll->MiddleRight.Floor > 0)
|
||||
{
|
||||
coll->MiddleRight.Floor = STOP_SIZE;
|
||||
}
|
||||
else if (coll->Setup.BlockCeilingSlope &&
|
||||
coll->MiddleRight.CeilingSlope)
|
||||
coll->MiddleRight.CeilingSlope)
|
||||
{
|
||||
coll->MiddleRight.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockDeathFloorDown &&
|
||||
coll->MiddleRight.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
coll->MiddleRight.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
{
|
||||
coll->MiddleRight.Floor = STOP_SIZE;
|
||||
}
|
||||
|
@ -647,19 +649,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
coll->FrontRight.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||
coll->FrontRight.FloorSlope &&
|
||||
coll->FrontRight.Floor > 0)
|
||||
coll->FrontRight.FloorSlope &&
|
||||
coll->FrontRight.Floor > 0)
|
||||
{
|
||||
coll->FrontRight.Floor = STOP_SIZE;
|
||||
}
|
||||
else if (coll->Setup.BlockCeilingSlope &&
|
||||
coll->FrontRight.CeilingSlope)
|
||||
coll->FrontRight.CeilingSlope)
|
||||
{
|
||||
coll->FrontRight.Floor = MAX_HEIGHT;
|
||||
}
|
||||
else if (coll->Setup.BlockDeathFloorDown &&
|
||||
coll->FrontRight.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
coll->FrontRight.Floor >= CLICK(0.5f) &&
|
||||
collResult.BottomBlock->Flags.Death)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -773,12 +775,20 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
quarter %= 2;
|
||||
|
||||
if (coll->MiddleLeft.HasFlippedDiagonalSplit())
|
||||
if (quarter) coll->CollisionType = CT_LEFT;
|
||||
{
|
||||
if (quarter)
|
||||
coll->CollisionType = CT_LEFT;
|
||||
}
|
||||
else
|
||||
if (!quarter) coll->CollisionType = CT_LEFT;
|
||||
{
|
||||
if (!quarter)
|
||||
coll->CollisionType = CT_LEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
coll->CollisionType = CT_LEFT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -815,16 +825,24 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
|||
|
||||
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;
|
||||
|
||||
if (coll->MiddleRight.HasFlippedDiagonalSplit())
|
||||
if (quarter) coll->CollisionType = CT_RIGHT;
|
||||
{
|
||||
if (quarter)
|
||||
coll->CollisionType = CT_RIGHT;
|
||||
}
|
||||
else
|
||||
if (!quarter) coll->CollisionType = CT_RIGHT;
|
||||
{
|
||||
if (!quarter)
|
||||
coll->CollisionType = CT_RIGHT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
coll->CollisionType = CT_RIGHT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include "Math/Math.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/game_object_ids.h"
|
||||
|
||||
struct ItemInfo;
|
||||
struct CollisionInfo;
|
||||
|
@ -87,10 +87,11 @@ struct CollisionSetup
|
|||
bool EnableSpasm; // Convulse when pushed
|
||||
|
||||
// Preserve old parameters to restore later
|
||||
Vector3i OldPosition;
|
||||
int OldAnimNumber;
|
||||
int OldFrameNumber;
|
||||
int OldState;
|
||||
Vector3i OldPosition = Vector3i::Zero;
|
||||
GAME_OBJECT_ID PrevAnimObjectID = ID_NO_OBJECT;
|
||||
int OldAnimNumber = 0;
|
||||
int OldFrameNumber = 0;
|
||||
int OldState = 0;
|
||||
};
|
||||
|
||||
struct CollisionInfo
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include "Game/items.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
|
||||
int FloorInfo::GetSurfacePlaneIndex(int x, int z, bool isFloor) const
|
||||
|
@ -313,7 +313,7 @@ void FloorInfo::RemoveBridge(int itemNumber)
|
|||
BridgeItemNumbers.erase(itemNumber);
|
||||
}
|
||||
|
||||
namespace TEN::Floordata
|
||||
namespace TEN::Collision::Floordata
|
||||
{
|
||||
Vector3 GetSurfaceNormal(const Vector2& tilt, bool isFloor)
|
||||
{
|
||||
|
@ -756,26 +756,32 @@ namespace TEN::Floordata
|
|||
auto floor = &GetFloorSide(item.RoomNumber, x, z);
|
||||
floor->AddBridge(itemNumber);
|
||||
|
||||
const auto floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||
if (Objects[item.ObjectNumber].floorBorder != nullptr)
|
||||
{
|
||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||
if (!roomAbove)
|
||||
break;
|
||||
int floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||
{
|
||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||
if (!roomAbove.has_value())
|
||||
break;
|
||||
|
||||
floor = &GetFloorSide(*roomAbove, x, z);
|
||||
floor->AddBridge(itemNumber);
|
||||
floor = &GetFloorSide(*roomAbove, x, z);
|
||||
floor->AddBridge(itemNumber);
|
||||
}
|
||||
}
|
||||
|
||||
const auto ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||
|
||||
if (Objects[item.ObjectNumber].ceilingBorder != nullptr)
|
||||
{
|
||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||
if (!roomBelow)
|
||||
break;
|
||||
int ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||
{
|
||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||
if (!roomBelow.has_value())
|
||||
break;
|
||||
|
||||
floor = &GetFloorSide(*roomBelow, x, z);
|
||||
floor->AddBridge(itemNumber);
|
||||
floor = &GetFloorSide(*roomBelow, x, z);
|
||||
floor->AddBridge(itemNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,29 +791,35 @@ namespace TEN::Floordata
|
|||
x += item.Pose.Position.x;
|
||||
z += item.Pose.Position.z;
|
||||
|
||||
auto floor = &GetFloorSide(item.RoomNumber, x, z);
|
||||
auto* floor = &GetFloorSide(item.RoomNumber, x, z);
|
||||
floor->RemoveBridge(itemNumber);
|
||||
|
||||
const auto floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||
if (Objects[item.ObjectNumber].floorBorder != nullptr)
|
||||
{
|
||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||
if (!roomAbove)
|
||||
break;
|
||||
int floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||
{
|
||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||
if (!roomAbove.has_value())
|
||||
break;
|
||||
|
||||
floor = &GetFloorSide(*roomAbove, x, z);
|
||||
floor->RemoveBridge(itemNumber);
|
||||
floor = &GetFloorSide(*roomAbove, x, z);
|
||||
floor->RemoveBridge(itemNumber);
|
||||
}
|
||||
}
|
||||
|
||||
const auto ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||
if (Objects[item.ObjectNumber].ceilingBorder != nullptr)
|
||||
{
|
||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||
if (!roomBelow)
|
||||
break;
|
||||
int ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||
{
|
||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||
if (!roomBelow.has_value())
|
||||
break;
|
||||
|
||||
floor = &GetFloorSide(*roomBelow, x, z);
|
||||
floor->RemoveBridge(itemNumber);
|
||||
floor = &GetFloorSide(*roomBelow, x, z);
|
||||
floor->RemoveBridge(itemNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,17 +836,20 @@ namespace TEN::Floordata
|
|||
auto bounds = GameBoundingBox(item);
|
||||
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))
|
||||
{
|
||||
return std::optional{ item->Pose.Position.y + (bottom ? bounds.Y2 : bounds.Y1) };
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
auto item = &g_Level.Items[itemNumber];
|
||||
|
@ -847,6 +862,7 @@ namespace TEN::Floordata
|
|||
void UpdateBridgeItem(int itemNumber, bool forceRemoval)
|
||||
{
|
||||
auto item = &g_Level.Items[itemNumber];
|
||||
if (!Objects[item->ObjectNumber].loaded) return;
|
||||
|
||||
// Force removal if object was killed
|
||||
if (item->Flags & IFLAG_KILLED)
|
||||
|
@ -873,10 +889,10 @@ namespace TEN::Floordata
|
|||
{
|
||||
for (int z = 0; z < room->zSize; z++)
|
||||
{
|
||||
auto pX = room->x + (x * BLOCK(1)) + BLOCK(0.5f);
|
||||
auto pZ = room->z + (z * BLOCK(1)) + BLOCK(0.5f);
|
||||
auto offX = pX - item->Pose.Position.x;
|
||||
auto offZ = pZ - item->Pose.Position.z;
|
||||
float pX = room->x + (x * BLOCK(1)) + BLOCK(0.5f);
|
||||
float pZ = room->z + (z * BLOCK(1)) + BLOCK(0.5f);
|
||||
float offX = pX - item->Pose.Position.x;
|
||||
float offZ = pZ - item->Pose.Position.z;
|
||||
|
||||
// Clean previous bridge state
|
||||
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.
|
||||
// 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.
|
||||
// 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.
|
||||
// Room number: Unique numeric index of a room.
|
||||
// Surface: Floor or ceiling.
|
||||
// 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));
|
||||
|
||||
enum class MaterialType
|
||||
|
@ -154,7 +158,7 @@ class FloorInfo
|
|||
void RemoveBridge(int itemNumber);
|
||||
};
|
||||
|
||||
namespace TEN::Floordata
|
||||
namespace TEN::Collision::Floordata
|
||||
{
|
||||
// TODO: Use normals natively.
|
||||
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);
|
||||
int GetBridgeBorder(int itemNumber, bool bottom);
|
||||
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/items.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/control/control.h"
|
||||
#include "Game/control/lot.h"
|
||||
#include "Game/effects/smoke.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/itemdata/creature_info.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
|
@ -15,12 +16,14 @@
|
|||
#include "Game/misc.h"
|
||||
#include "Game/pickup/pickup.h"
|
||||
#include "Game/room.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Objects/TR5/Object/tr5_pushableblock.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
|
||||
using namespace TEN::Effects::Smoke;
|
||||
|
||||
constexpr auto ESCAPE_DIST = SECTOR(5);
|
||||
constexpr auto STALK_DIST = SECTOR(3);
|
||||
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_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
||||
|
||||
constexpr auto CREATURE_GUN_EFFECT_VERTICAL_OFFSET = 75;
|
||||
|
||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||
constexpr int HIGH_PRIO_RANGE = 8;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
||||
item->Animation.ActiveState = entityKillState;
|
||||
auto& playerItem = *LaraItem;
|
||||
auto& player = GetLaraInfo(playerItem);
|
||||
|
||||
LaraItem->Animation.AnimNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex + laraExtraKillAnim;
|
||||
LaraItem->Animation.FrameNumber = g_Level.Anims[LaraItem->Animation.AnimNumber].frameBase;
|
||||
LaraItem->Animation.ActiveState = 0;
|
||||
LaraItem->Animation.TargetState = laraKillState;
|
||||
SetAnimation(*creatureItem, creatureAnimNumber);
|
||||
SetAnimation(playerItem, ID_LARA_EXTRA_ANIMS, playerAnimNumber);
|
||||
|
||||
LaraItem->Pose = item->Pose;
|
||||
LaraItem->Animation.IsAirborne = false;
|
||||
LaraItem->Animation.Velocity.z = 0;
|
||||
LaraItem->Animation.Velocity.y = 0;
|
||||
playerItem.Pose = creatureItem->Pose;
|
||||
playerItem.Animation.IsAirborne = false;
|
||||
playerItem.Animation.Velocity = Vector3::Zero;
|
||||
|
||||
if (item->RoomNumber != LaraItem->RoomNumber)
|
||||
ItemNewRoom(Lara.ItemNumber, item->RoomNumber);
|
||||
if (creatureItem->RoomNumber != playerItem.RoomNumber)
|
||||
ItemNewRoom(player.ItemNumber, creatureItem->RoomNumber);
|
||||
|
||||
AnimateItem(LaraItem);
|
||||
AnimateItem(&playerItem);
|
||||
|
||||
Lara.ExtraAnim = 1;
|
||||
Lara.Control.HandStatus = HandStatus::Busy;
|
||||
Lara.Control.Weapon.GunType = LaraWeaponType::None;
|
||||
Lara.HitDirection = -1;
|
||||
player.ExtraAnim = 1;
|
||||
player.Control.HandStatus = HandStatus::Busy;
|
||||
player.Control.Weapon.GunType = LaraWeaponType::None;
|
||||
player.HitDirection = -1;
|
||||
|
||||
Camera.pos.RoomNumber = LaraItem->RoomNumber;
|
||||
Camera.pos.RoomNumber = playerItem.RoomNumber;
|
||||
Camera.type = CameraType::Chase;
|
||||
Camera.flags = CF_FOLLOW_CENTER;
|
||||
Camera.targetAngle = ANGLE(170.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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -660,7 +652,7 @@ void CreatureFloat(short itemNumber)
|
|||
|
||||
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->Collidable = false;
|
||||
|
@ -735,26 +727,47 @@ short CreatureTurn(ItemInfo* item, short maxTurn)
|
|||
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;
|
||||
|
||||
auto prevPos = item->Pose.Position;
|
||||
auto& creature = *GetCreatureInfo(&item);
|
||||
|
||||
AnimateItem(item);
|
||||
ProcessSectorFlags(item);
|
||||
CreatureHealth(item);
|
||||
SpawnCreatureGunEffect(item, creature.MuzzleFlash[0]);
|
||||
SpawnCreatureGunEffect(item, creature.MuzzleFlash[1]);
|
||||
|
||||
if (item->Status == ITEM_DEACTIVATED)
|
||||
auto prevPos = item.Pose.Position;
|
||||
|
||||
AnimateItem(&item);
|
||||
ProcessSectorFlags(&item);
|
||||
CreatureHealth(&item);
|
||||
|
||||
if (item.Status == ITEM_DEACTIVATED)
|
||||
{
|
||||
CreatureDie(itemNumber, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CreaturePathfind(item, prevPos, angle, tilt);
|
||||
return CreaturePathfind(&item, prevPos, headingAngle, tiltAngle);
|
||||
}
|
||||
|
||||
void CreatureHealth(ItemInfo* item)
|
||||
|
@ -1088,7 +1101,7 @@ bool CreatureActive(short itemNumber)
|
|||
return true;
|
||||
}
|
||||
|
||||
void InitialiseCreature(short itemNumber)
|
||||
void InitializeCreature(short itemNumber)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
|
||||
|
@ -2097,7 +2110,7 @@ void AdjustStopperFlag(ItemInfo* item, int direction)
|
|||
floor->Stopper = !floor->Stopper;
|
||||
}
|
||||
|
||||
void InitialiseItemBoxData()
|
||||
void InitializeItemBoxData()
|
||||
{
|
||||
for (int i = 0; i < g_Level.Items.size(); i++)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "Specific/level.h"
|
||||
#include "Math/Math.h"
|
||||
|
||||
struct BiteInfo;
|
||||
struct CreatureBiteInfo;
|
||||
struct CreatureInfo;
|
||||
struct ItemInfo;
|
||||
struct LOTInfo;
|
||||
|
@ -20,55 +20,6 @@ enum TARGET_TYPE
|
|||
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
|
||||
{
|
||||
int zoneNumber;
|
||||
|
@ -99,30 +50,6 @@ struct OVERLAP
|
|||
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)
|
||||
|
||||
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 AlertAllGuards(short itemNumber);
|
||||
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 CreatureEffect(ItemInfo* item, BiteInfo bite, std::function<CreatureEffectFunction> func);
|
||||
short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function<CreatureEffectFunction> func);
|
||||
short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function<CreatureEffectFunction> func);
|
||||
void CreatureUnderwater(ItemInfo* item, int depth);
|
||||
void CreatureFloat(short itemNumber);
|
||||
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 SearchLOT(LOTInfo* LOT, int expansion);
|
||||
bool CreatureActive(short itemNumber);
|
||||
void InitialiseCreature(short itemNumber);
|
||||
void InitializeCreature(short itemNumber);
|
||||
bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber);
|
||||
void CreatureAIInfo(ItemInfo* item, AI_INFO* AI);
|
||||
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 AdjustStopperFlag(ItemInfo* item, int direction);
|
||||
void InitialiseItemBoxData();
|
||||
void InitializeItemBoxData();
|
||||
|
||||
bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/Electricity.h"
|
||||
#include "Game/effects/explosion.h"
|
||||
#include "Game/effects/footprint.h"
|
||||
#include "Game/effects/Footprint.h"
|
||||
#include "Game/effects/Hair.h"
|
||||
#include "Game/effects/Ripple.h"
|
||||
#include "Game/effects/simple_particle.h"
|
||||
|
@ -36,6 +36,7 @@
|
|||
#include "Game/pickup/pickup.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Game/spotcam.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Effects/tr4_locusts.h"
|
||||
|
@ -54,7 +55,6 @@
|
|||
#include "Specific/clock.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Specific/winmain.h"
|
||||
|
||||
using namespace std::chrono;
|
||||
|
@ -65,7 +65,7 @@ using namespace TEN::Effects::Drip;
|
|||
using namespace TEN::Effects::Electricity;
|
||||
using namespace TEN::Effects::Environment;
|
||||
using namespace TEN::Effects::Explosion;
|
||||
using namespace TEN::Effects::Footprints;
|
||||
using namespace TEN::Effects::Footprint;
|
||||
using namespace TEN::Effects::Hair;
|
||||
using namespace TEN::Effects::Ripple;
|
||||
using namespace TEN::Effects::Smoke;
|
||||
|
@ -74,7 +74,7 @@ using namespace TEN::Effects::Streamer;
|
|||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Entities::Switches;
|
||||
using namespace TEN::Entities::TR4;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Hud;
|
||||
using namespace TEN::Input;
|
||||
using namespace TEN::Math;
|
||||
|
@ -84,7 +84,7 @@ int GameTimer = 0;
|
|||
int GlobalCounter = 0;
|
||||
int Wibble = 0;
|
||||
|
||||
bool InitialiseGame;
|
||||
bool InitializeGame;
|
||||
bool DoTheGame;
|
||||
bool JustLoaded;
|
||||
bool ThreadEnded;
|
||||
|
@ -124,7 +124,6 @@ GameStatus ControlPhase(int numFrames)
|
|||
{
|
||||
auto time1 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto* level = g_GameFlow->GetLevel(CurrentLevel);
|
||||
bool isTitle = (CurrentLevel == 0);
|
||||
|
||||
RegeneratePickups();
|
||||
|
@ -271,7 +270,6 @@ unsigned CALLBACK GameMain(void *)
|
|||
else
|
||||
g_Renderer.RenderTitleImage();
|
||||
|
||||
|
||||
// Execute the Lua gameflow and play the game.
|
||||
g_GameFlow->DoFlow();
|
||||
|
||||
|
@ -296,17 +294,17 @@ GameStatus DoLevel(int levelIndex, bool loadGame)
|
|||
|
||||
// Initialize items, effects, lots, and cameras.
|
||||
HairEffect.Initialize();
|
||||
InitialiseFXArray(true);
|
||||
InitialiseCamera();
|
||||
InitialiseSpotCamSequences(isTitle);
|
||||
InitialiseItemBoxData();
|
||||
InitializeFXArray(true);
|
||||
InitializeCamera();
|
||||
InitializeSpotCamSequences(isTitle);
|
||||
InitializeItemBoxData();
|
||||
|
||||
// Initialize scripting.
|
||||
InitialiseScripting(levelIndex, loadGame);
|
||||
InitialiseNodeScripts();
|
||||
InitializeScripting(levelIndex, loadGame);
|
||||
InitializeNodeScripts();
|
||||
|
||||
// Initialize game variables and optionally load game.
|
||||
InitialiseOrLoadGame(loadGame);
|
||||
InitializeOrLoadGame(loadGame);
|
||||
|
||||
// Prepare title menu, if necessary.
|
||||
if (isTitle)
|
||||
|
@ -416,6 +414,7 @@ void CleanUp()
|
|||
StreamerEffect.Clear();
|
||||
ClearUnderwaterBloodParticles();
|
||||
ClearBubbles();
|
||||
ClearFootprints();
|
||||
ClearDrips();
|
||||
ClearRipples();
|
||||
DisableSmokeParticles();
|
||||
|
@ -438,7 +437,7 @@ void CleanUp()
|
|||
ClearObjCamera();
|
||||
}
|
||||
|
||||
void InitialiseScripting(int levelIndex, bool loadGame)
|
||||
void InitializeScripting(int levelIndex, bool loadGame)
|
||||
{
|
||||
TENLog("Loading level script...", LogLevel::Info);
|
||||
|
||||
|
@ -465,9 +464,9 @@ void InitialiseScripting(int levelIndex, bool loadGame)
|
|||
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_GameScriptEntities->FreeEntities();
|
||||
|
||||
|
@ -475,7 +474,7 @@ void DeInitialiseScripting(int levelIndex)
|
|||
g_GameScript->ResetScripts(true);
|
||||
}
|
||||
|
||||
void InitialiseOrLoadGame(bool loadGame)
|
||||
void InitializeOrLoadGame(bool loadGame)
|
||||
{
|
||||
RequiredStartPos = false;
|
||||
|
||||
|
@ -495,7 +494,7 @@ void InitialiseOrLoadGame(bool loadGame)
|
|||
Camera.target.y = LaraItem->Pose.Position.y;
|
||||
Camera.target.z = LaraItem->Pose.Position.z;
|
||||
|
||||
InitialiseGame = false;
|
||||
InitializeGame = false;
|
||||
|
||||
g_GameFlow->SelectedSaveGame = 0;
|
||||
g_GameScript->OnLoad();
|
||||
|
@ -505,12 +504,12 @@ void InitialiseOrLoadGame(bool loadGame)
|
|||
// If not loading a savegame, clear all info.
|
||||
Statistics.Level = {};
|
||||
|
||||
if (InitialiseGame)
|
||||
if (InitializeGame)
|
||||
{
|
||||
// Clear all game info as well.
|
||||
Statistics.Game = {};
|
||||
GameTimer = 0;
|
||||
InitialiseGame = false;
|
||||
InitializeGame = false;
|
||||
|
||||
TENLog("Starting new game.", LogLevel::Info);
|
||||
}
|
||||
|
@ -563,6 +562,7 @@ GameStatus DoGameLoop(int levelIndex)
|
|||
else
|
||||
{
|
||||
if (result == GameStatus::ExitToTitle ||
|
||||
result == GameStatus::LaraDead ||
|
||||
result == GameStatus::LoadGame ||
|
||||
result == GameStatus::LevelComplete)
|
||||
{
|
||||
|
@ -574,13 +574,13 @@ GameStatus DoGameLoop(int levelIndex)
|
|||
Sound_UpdateScene();
|
||||
}
|
||||
|
||||
EndGameLoop(levelIndex);
|
||||
EndGameLoop(levelIndex, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EndGameLoop(int levelIndex)
|
||||
void EndGameLoop(int levelIndex, GameStatus reason)
|
||||
{
|
||||
DeInitialiseScripting(levelIndex);
|
||||
DeInitializeScripting(levelIndex, reason);
|
||||
|
||||
StopAllSounds();
|
||||
StopSoundTracks();
|
||||
|
@ -678,7 +678,7 @@ GameStatus HandleGlobalInputEvents(bool isTitle)
|
|||
if (Lara.Control.Count.Death > DEATH_NO_INPUT_TIMEOUT ||
|
||||
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?
|
||||
|
|
|
@ -50,7 +50,7 @@ extern int RumbleTimer;
|
|||
extern int GlobalCounter;
|
||||
extern int Wibble;
|
||||
|
||||
extern bool InitialiseGame;
|
||||
extern bool InitializeGame;
|
||||
extern bool DoTheGame;
|
||||
extern bool JustLoaded;
|
||||
extern bool ThreadEnded;
|
||||
|
@ -77,7 +77,7 @@ int DrawPhase(bool isTitle);
|
|||
GameStatus ControlPhase(int numFrames);
|
||||
GameStatus DoLevel(int levelIndex, bool loadGame = false);
|
||||
GameStatus DoGameLoop(int levelIndex);
|
||||
void EndGameLoop(int levelIndex);
|
||||
void EndGameLoop(int levelIndex, GameStatus reason);
|
||||
|
||||
GameStatus HandleMenuCalls(bool isTitle);
|
||||
GameStatus HandleGlobalInputEvents(bool isTitle);
|
||||
|
@ -92,8 +92,8 @@ void UpdateShatters();
|
|||
|
||||
void CleanUp();
|
||||
|
||||
void InitialiseOrLoadGame(bool loadGame);
|
||||
void InitialiseScripting(int levelIndex, bool loadGame);
|
||||
void DeInitialiseScripting(int levelIndex);
|
||||
void InitializeOrLoadGame(bool loadGame);
|
||||
void InitializeScripting(int levelIndex, bool loadGame);
|
||||
void DeInitializeScripting(int levelIndex);
|
||||
|
||||
unsigned CALLBACK GameMain(void*);
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
#include "Game/effects/Hair.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/effects/weather.h"
|
||||
#include "Game/effects/footprint.h"
|
||||
#include "Game/effects/Footprint.h"
|
||||
#include "Game/effects/debris.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_fire.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/pickup/pickup.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
||||
|
@ -25,7 +25,7 @@
|
|||
#include "Objects/Effects/tr4_locusts.h"
|
||||
|
||||
using namespace TEN::Effects::Environment;
|
||||
using namespace TEN::Effects::Footprints;
|
||||
using namespace TEN::Effects::Footprint;
|
||||
using namespace TEN::Effects::Hair;
|
||||
|
||||
int FlipEffect;
|
||||
|
@ -121,12 +121,12 @@ void Puzzle(ItemInfo* item)
|
|||
|
||||
void AddLeftFootprint(ItemInfo* item)
|
||||
{
|
||||
AddFootprint(item, false);
|
||||
SpawnFootprint(*item, false);
|
||||
}
|
||||
|
||||
void AddRightFootprint(ItemInfo* item)
|
||||
{
|
||||
AddFootprint(item, true);
|
||||
SpawnFootprint(*item, true);
|
||||
}
|
||||
|
||||
void ResetHair(ItemInfo* item)
|
||||
|
@ -155,7 +155,7 @@ void DrawLeftPistol(ItemInfo* item)
|
|||
|
||||
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;
|
||||
}
|
||||
else
|
||||
|
@ -171,7 +171,7 @@ void DrawRightPistol(ItemInfo* item)
|
|||
|
||||
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;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara_fire.h"
|
||||
#include "Game/Lara/lara_one_gun.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Objects/Generic/Object/objects.h"
|
||||
#include "Objects/Generic/Switches/switch.h"
|
||||
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
||||
#include "ScriptInterfaceGame.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
int NumberLosRooms;
|
||||
short LosRooms[20];
|
||||
|
@ -252,7 +252,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo
|
|||
else
|
||||
{
|
||||
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 (isFiring && LaserSight)
|
||||
FireCrossBowFromLaserSight(LaraItem, origin, &target2);
|
||||
FireCrossBowFromLaserSight(*LaraItem, origin, &target2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/misc.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
#define DEFAULT_FLY_UPDOWN_SPEED 16
|
||||
#define DEFAULT_SWIM_UPDOWN_SPEED 32
|
||||
|
@ -16,15 +16,15 @@
|
|||
int SlotsUsed;
|
||||
std::vector<CreatureInfo*> ActiveCreatures;
|
||||
|
||||
void InitialiseLOTarray(int itemNumber)
|
||||
void InitializeLOTarray(int itemNumber)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
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.Initialised = true;
|
||||
creature->LOT.Initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ bool EnableEntityAI(short itemNum, bool always, bool makeTarget)
|
|||
if (item->IsCreature())
|
||||
return true;
|
||||
|
||||
InitialiseSlot(itemNum, makeTarget);
|
||||
InitializeSlot(itemNum, makeTarget);
|
||||
ActiveCreatures.push_back(item->Data);
|
||||
|
||||
return item->IsCreature();
|
||||
|
@ -55,14 +55,14 @@ void DisableEntityAI(short itemNumber)
|
|||
item->Data = nullptr;
|
||||
}
|
||||
|
||||
void InitialiseSlot(short itemNumber, bool makeTarget)
|
||||
void InitializeSlot(short itemNumber, bool makeTarget)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
auto* object = &Objects[item->ObjectNumber];
|
||||
item->Data = CreatureInfo();
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
|
||||
InitialiseLOTarray(itemNumber);
|
||||
InitializeLOTarray(itemNumber);
|
||||
creature->ItemNumber = itemNumber;
|
||||
creature->Mood = MoodType::Bored;
|
||||
creature->JointRotation[0] = 0;
|
||||
|
@ -146,6 +146,12 @@ void InitialiseSlot(short itemNumber, bool makeTarget)
|
|||
|
||||
break;
|
||||
|
||||
case LotType::SnowmobileGun:
|
||||
creature->LOT.Step = CLICK(1);
|
||||
creature->LOT.Drop = -BLOCK(1);
|
||||
creature->LOT.Zone = ZoneType::Human;
|
||||
break;
|
||||
|
||||
// Can climb.
|
||||
case LotType::Human:
|
||||
creature->LOT.Step = BLOCK(1);
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
extern std::vector<CreatureInfo*> ActiveCreatures;
|
||||
|
||||
void InitialiseLOTarray(int allocMem);
|
||||
void InitializeLOTarray(int allocMem);
|
||||
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 DisableEntityAI(short itemNumber);
|
||||
void ClearLOT(LOTInfo* LOT);
|
||||
|
|
|
@ -15,13 +15,14 @@
|
|||
#include "Game/Lara/lara_tests.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Game/spotcam.h"
|
||||
#include "Objects/Generic/Switches/generic_switch.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Objects/TR3/Vehicles/kayak.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Entities::Switches;
|
||||
|
@ -82,7 +83,8 @@ bool GetKeyTrigger(ItemInfo* item)
|
|||
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);
|
||||
|
||||
|
@ -95,14 +97,14 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
|||
return 0;
|
||||
|
||||
trigger += 2;
|
||||
short* current = itemNos;
|
||||
short* currentPtr = itemNumbersPtr;
|
||||
int k = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (TRIG_BITS(*trigger) == TO_OBJECT && item != &g_Level.Items[*trigger & VALUE_BITS])
|
||||
{
|
||||
current[k] = *trigger & VALUE_BITS;
|
||||
currentPtr[k] = *trigger & VALUE_BITS;
|
||||
++k;
|
||||
}
|
||||
|
||||
|
@ -121,10 +123,67 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
|||
int SwitchTrigger(short itemNumber, short timer)
|
||||
{
|
||||
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.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)
|
||||
{
|
||||
item.Timer = timer;
|
||||
|
@ -135,14 +194,15 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.TriggerFlags >= 0 || item.Animation.ActiveState)
|
||||
|
||||
if (item.TriggerFlags >= 0 || item.Animation.ActiveState != 0)
|
||||
{
|
||||
RemoveActiveItem(itemNumber);
|
||||
|
||||
item.Status = ITEM_NOT_ACTIVE;
|
||||
if (!item.ItemFlags[0] == 0)
|
||||
item.Flags |= ONESHOT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -151,11 +211,11 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
else if (item.Status)
|
||||
else if (item.Status != 0)
|
||||
{
|
||||
if (item.ObjectNumber == ID_AIRLOCK_SWITCH &&
|
||||
item.Animation.AnimNumber == GetAnimNumber(item, 2) &&
|
||||
item.Animation.FrameNumber == GetFrameNumber(&item, 0))
|
||||
item.Animation.AnimNumber == GetAnimIndex(item, 2) &&
|
||||
item.Animation.FrameNumber == GetFrameIndex(&item, 0))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -170,15 +230,18 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int KeyTrigger(short itemNum)
|
||||
int KeyTrigger(short itemNumber)
|
||||
{
|
||||
ItemInfo* item = &g_Level.Items[itemNum];
|
||||
int oldkey;
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
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;
|
||||
}
|
||||
|
||||
oldkey = KeyTriggerActive;
|
||||
int oldkey = KeyTriggerActive;
|
||||
|
||||
if (!oldkey)
|
||||
item->Status = ITEM_DEACTIVATED;
|
||||
|
@ -188,9 +251,9 @@ int KeyTrigger(short itemNum)
|
|||
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)) ||
|
||||
item->Status != ITEM_INVISIBLE ||
|
||||
|
@ -200,7 +263,7 @@ bool PickupTrigger(short itemNum)
|
|||
return false;
|
||||
}
|
||||
|
||||
KillItem(itemNum);
|
||||
KillItem(itemNumber);
|
||||
item->Flags |= IFLAG_CLEAR_BODY;
|
||||
|
||||
return true;
|
||||
|
@ -237,6 +300,7 @@ void RefreshCamera(short type, short* data)
|
|||
}
|
||||
else
|
||||
targetOk = 0;
|
||||
|
||||
break;
|
||||
|
||||
case TO_TARGET:
|
||||
|
@ -250,7 +314,7 @@ void RefreshCamera(short type, short* data)
|
|||
|
||||
if (Camera.item)
|
||||
if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem))
|
||||
Camera.item = NULL;
|
||||
Camera.item = nullptr;
|
||||
|
||||
if (Camera.number == -1 && Camera.timer > 0)
|
||||
Camera.timer = -1;
|
||||
|
@ -498,8 +562,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
short targetType = 0;
|
||||
short trigger = 0;
|
||||
|
||||
ItemInfo* item = NULL;
|
||||
ItemInfo* cameraItem = NULL;
|
||||
ItemInfo* item = nullptr;
|
||||
ItemInfo* cameraItem = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -642,7 +706,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
UseSpotCam = true;
|
||||
if (LastSpotCamSequence != value)
|
||||
TrackCameraInit = false;
|
||||
InitialiseSpotCam(value);
|
||||
InitializeSpotCam(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +717,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
break;
|
||||
|
||||
case TO_SINK:
|
||||
Lara.WaterCurrentActive = value + 1;
|
||||
Lara.Context.WaterCurrentActive = value + 1;
|
||||
break;
|
||||
|
||||
case TO_FLIPMAP:
|
||||
|
@ -761,12 +825,12 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
FlipEffect = newEffect;
|
||||
}
|
||||
|
||||
void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags)
|
||||
void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags)
|
||||
{
|
||||
auto roomNum = item->RoomNumber;
|
||||
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNum);
|
||||
auto roomNumber = item->RoomNumber;
|
||||
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)
|
||||
|
|
|
@ -67,16 +67,16 @@ extern int TriggerTimer;
|
|||
extern int KeyTriggerActive;
|
||||
|
||||
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 KeyTrigger(short itemNum);
|
||||
bool PickupTrigger(short itemNum);
|
||||
int KeyTrigger(short itemNumber);
|
||||
bool PickupTrigger(short itemNumber);
|
||||
void RefreshCamera(short type, short* data);
|
||||
int TriggerActive(ItemInfo* item);
|
||||
short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z);
|
||||
short* GetTriggerIndex(ItemInfo* item);
|
||||
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 Antitrigger(short const value, short const flags = 0);
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
#include "Game/Lara/lara.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Renderer/Renderer11Enums.h"
|
||||
#include "Scripting/Include/ScriptInterfaceGame.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
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);
|
||||
|
||||
if (item.IsLara() || item.Index == Lara.Vehicle)
|
||||
if (item.IsLara() || item.Index == Lara.Context.Vehicle)
|
||||
{
|
||||
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/";
|
||||
|
||||
|
@ -207,10 +207,18 @@ namespace TEN::Control::Volumes
|
|||
TENLog("Loading node scripts...", LogLevel::Info);
|
||||
|
||||
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;
|
||||
for (const auto& set : g_Level.EventSets)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
#include "Game/control/volumeactivator.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
struct CollisionSetup;
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace TEN::Control::Volumes
|
|||
void TestVolumes(CAMERA_INFO* camera);
|
||||
|
||||
void HandleEvent(VolumeEvent& event, VolumeActivator& activator);
|
||||
void InitialiseNodeScripts();
|
||||
void InitializeNodeScripts();
|
||||
}
|
||||
|
||||
// TODO: Move into namespace and deal with errors.
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace TEN::Control::Volumes
|
|||
|
||||
struct VolumeEventSet
|
||||
{
|
||||
std::string Name = {};
|
||||
std::string Name = {};
|
||||
VolumeActivatorFlags Activators = VolumeActivatorFlags::None;
|
||||
|
||||
VolumeEvent OnEnter = {};
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Utils/object_helper.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
@ -17,6 +18,9 @@ namespace TEN::Effects::Blood
|
|||
|
||||
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_MIN = 8.0f;
|
||||
constexpr auto SPAWN_RADIUS = BLOCK(0.25f);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/people.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include "Game/effects/Ripple.h"
|
||||
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace TEN::Effects::Streamer
|
|||
|
||||
public:
|
||||
// Members
|
||||
std::map<int, std::vector<Streamer>> Pools = {}; // Key = tag.
|
||||
std::unordered_map<int, std::vector<Streamer>> Pools = {}; // Key = tag.
|
||||
|
||||
// Utilities
|
||||
void AddStreamer(int tag, const Vector3& pos, const Vector3& direction, short orient2D, const Vector4& color,
|
||||
|
@ -92,7 +92,7 @@ namespace TEN::Effects::Streamer
|
|||
|
||||
public:
|
||||
// Members
|
||||
std::map<int, StreamerModule> Modules = {}; // Key = entity number.
|
||||
std::unordered_map<int, StreamerModule> Modules = {}; // Key = entity number.
|
||||
|
||||
// Utilities
|
||||
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/effects/effects.h"
|
||||
#include "Game/effects/Ripple.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Ripple;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
|
||||
namespace TEN::Effects::Bubble
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Renderer/Renderer11Enums.h"
|
||||
#include "Sound/sound.h"
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#include "Game/effects/debris.h"
|
||||
|
||||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Math/Random.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include <Game/effects/tomb4fx.h>
|
||||
|
||||
using std::vector;
|
||||
using namespace TEN::Renderer;
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
#include "Game/effects/Ripple.h"
|
||||
#include "Game/effects/weather.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Environment;
|
||||
using namespace TEN::Effects::Ripple;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
|
||||
namespace TEN::Effects::Drip
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Blood;
|
||||
using namespace TEN::Effects::Bubble;
|
||||
|
@ -52,7 +52,7 @@ int SplashCount = 0;
|
|||
Vector3i NodeVectors[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
|
||||
{ 0, 0, 256, 8, false }, // TR5 offset 2
|
||||
{ 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->friction = 0;
|
||||
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->gravity = 0;
|
||||
spark->maxYvel = 0;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/spark.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
|
|
@ -1,264 +1,222 @@
|
|||
#include "framework.h"
|
||||
#include "Game/effects/footprint.h"
|
||||
#include "Game/effects/Footprint.h"
|
||||
|
||||
#include "Game/animation.h"
|
||||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/collision/floordata.h"
|
||||
#include "Game/control/control.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Utils/object_helper.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
|
||||
namespace TEN::Effects::Footprints
|
||||
namespace TEN::Effects::Footprint
|
||||
{
|
||||
std::deque<FOOTPRINT_STRUCT> footprints = std::deque<FOOTPRINT_STRUCT>();
|
||||
|
||||
bool CheckFootOnFloor(const ItemInfo& item, int mesh, Vector3& outFootprintPosition)
|
||||
const auto FootprintMaterials = std::vector<MaterialType>
|
||||
{
|
||||
int x = item.Pose.Position.x;
|
||||
int y = item.Pose.Position.y;
|
||||
int z = item.Pose.Position.z;
|
||||
short roomNumber = item.RoomNumber;
|
||||
MaterialType::Mud,
|
||||
MaterialType::Snow,
|
||||
MaterialType::Sand,
|
||||
MaterialType::Gravel,
|
||||
MaterialType::Custom1,
|
||||
MaterialType::Custom2,
|
||||
MaterialType::Custom3,
|
||||
MaterialType::Custom4
|
||||
};
|
||||
|
||||
auto floor = GetFloor(x, y, z, &roomNumber);
|
||||
auto pos = GetJointPosition(LaraItem, mesh, Vector3i(0, FOOT_HEIGHT_OFFSET, 0));
|
||||
int height = GetFloorHeight(floor, pos.x, pos.y - CLICK(1), pos.z);
|
||||
struct FootprintPositionData
|
||||
{
|
||||
bool CanSpawn = false;
|
||||
Vector3 Position = Vector3::Zero;
|
||||
};
|
||||
|
||||
outFootprintPosition.x = pos.x;
|
||||
outFootprintPosition.y = height - 8;
|
||||
outFootprintPosition.z = pos.z;
|
||||
std::vector<Footprint> Footprints = {};
|
||||
|
||||
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)
|
||||
return;
|
||||
constexpr auto SCALE = BLOCK(1 / 16.0f);
|
||||
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.
|
||||
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)
|
||||
return std::array<Vector3, Footprint::VERTEX_COUNT>
|
||||
{
|
||||
case MaterialType::Concrete:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS;
|
||||
break;
|
||||
pos + Vector3::Transform(POINT_0, rotMatrix),
|
||||
pos + Vector3::Transform(POINT_1, rotMatrix),
|
||||
pos + Vector3::Transform(POINT_2, rotMatrix),
|
||||
pos + Vector3::Transform(POINT_3, rotMatrix)
|
||||
};
|
||||
}
|
||||
|
||||
case MaterialType::Grass:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRASS;
|
||||
break;
|
||||
static FootprintPositionData GetFootprintPositionData(const ItemInfo& item, int jointIndex)
|
||||
{
|
||||
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:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRAVEL;
|
||||
break;
|
||||
auto footPos = GetJointPosition(item, jointIndex, FOOT_OFFSET);
|
||||
int floorHeight = GetCollision(footPos.x, footPos.y - CLICK(1), footPos.z, item.RoomNumber).Position.Floor;
|
||||
|
||||
case MaterialType::Ice:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_ICE;
|
||||
break;
|
||||
bool canSpawn = (abs(footPos.y - floorHeight) < ABS_FLOOR_BOUND);
|
||||
auto pos = Vector3(footPos.x, floorHeight - SURFACE_OFFSET, footPos.z);
|
||||
return FootprintPositionData{ canSpawn, pos };
|
||||
}
|
||||
|
||||
case MaterialType::Marble:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MARBLE;
|
||||
break;
|
||||
static bool TestFootprintFloor(const ItemInfo& item, const Vector3& pos, const std::array<Vector3, Footprint::VERTEX_COUNT>& vertexPoints)
|
||||
{
|
||||
constexpr auto ABS_FLOOR_BOUND = CLICK(0.5f);
|
||||
|
||||
case MaterialType::Metal:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL;
|
||||
break;
|
||||
// Get point collision at every vertex point.
|
||||
auto pointColl0 = GetCollision(vertexPoints[0].x, pos.y - CLICK(1), vertexPoints[0].z, item.RoomNumber);
|
||||
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:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MUD;
|
||||
break;
|
||||
|
||||
case MaterialType::OldMetal:
|
||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL;
|
||||
break;
|
||||
|
||||
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;
|
||||
// Don't spawn footprint if floor heights at vertex points are outside upper/lower floor height bound.
|
||||
if ((abs(pointColl0.Position.Floor - pointColl1.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||
(abs(pointColl1.Position.Floor - pointColl2.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||
(abs(pointColl2.Position.Floor - pointColl3.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||
(abs(pointColl3.Position.Floor - pointColl0.Position.Floor) > ABS_FLOOR_BOUND))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// HACK: Must be here until reference WAD2 is revised.
|
||||
if (fx != SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS)
|
||||
SoundEffect(fx, &item->Pose);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (floor->Material != MaterialType::Sand &&
|
||||
floor->Material != MaterialType::Snow &&
|
||||
floor->Material != MaterialType::Gravel &&
|
||||
floor->Material != MaterialType::Mud &&
|
||||
floor->Material != MaterialType::Custom2 &&
|
||||
floor->Material != MaterialType::Custom1 &&
|
||||
floor->Material != MaterialType::Custom3 &&
|
||||
floor->Material != MaterialType::Custom4)
|
||||
{
|
||||
void SpawnFootprint(bool isRight, const std::array<Vector3, Footprint::VERTEX_COUNT>& vertexPoints)
|
||||
{
|
||||
if (!CheckIfSlotExists(ID_MISC_SPRITES, "Footprint rendering"))
|
||||
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.
|
||||
auto plane = floor->FloorCollision.Planes[floor->GetSurfacePlaneIndex(footPos.x, footPos.z, true)];
|
||||
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))
|
||||
// Check floor material.
|
||||
if (!TestMaterial(pointColl.BottomBlock->Material, FootprintMaterials))
|
||||
return;
|
||||
|
||||
// Don't process footprint placement if all foot corners aren't on the same height
|
||||
if ((abs(c0.Position.Floor - c1.Position.Floor) > STEP_SIZE / 2) ||
|
||||
(abs(c1.Position.Floor - c2.Position.Floor) > STEP_SIZE / 2) ||
|
||||
(abs(c2.Position.Floor - c3.Position.Floor) > STEP_SIZE / 2) ||
|
||||
(abs(c3.Position.Floor - c0.Position.Floor) > STEP_SIZE / 2))
|
||||
auto vertexPoints = GetFootprintVertexPoints(item, posData.Position, GetSurfaceNormal(pointColl.FloorTilt, true));
|
||||
|
||||
// Test floor continuity.
|
||||
if (!TestFootprintFloor(item, posData.Position, vertexPoints))
|
||||
return;
|
||||
|
||||
// Construct footprint
|
||||
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);
|
||||
SpawnFootprint(isRight, vertexPoints);
|
||||
}
|
||||
|
||||
void UpdateFootprints()
|
||||
{
|
||||
if (footprints.size() == 0)
|
||||
if (Footprints.empty())
|
||||
return;
|
||||
|
||||
int numInvalidFootprints = 0;
|
||||
|
||||
for (auto i = footprints.begin(); i != footprints.end(); i++)
|
||||
for (auto& footprint: Footprints)
|
||||
{
|
||||
FOOTPRINT_STRUCT& footprint = *i;
|
||||
footprint.Life--;
|
||||
|
||||
if (footprint.Life <= 0)
|
||||
{
|
||||
numInvalidFootprints++;
|
||||
if (footprint.Life <= 0.0f)
|
||||
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)
|
||||
{
|
||||
footprint.Opacity = footprint.StartOpacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
float opacity = Lerp(0.0f, footprint.StartOpacity, fmax(0, fmin(1, footprint.Life / (float)footprint.LifeStartFading)));
|
||||
footprint.Opacity = opacity;
|
||||
}
|
||||
// Update life.
|
||||
footprint.Life -= 1.0f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numInvalidFootprints; i++)
|
||||
{
|
||||
footprints.pop_back();
|
||||
}
|
||||
ClearInactiveEffects(Footprints);
|
||||
}
|
||||
|
||||
void ClearFootprints()
|
||||
{
|
||||
Footprints.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
#pragma once
|
||||
#include <deque>
|
||||
#include "Math/Math.h"
|
||||
|
||||
struct ItemInfo;
|
||||
|
||||
namespace TEN::Effects::Footprints
|
||||
namespace TEN::Effects::Footprint
|
||||
{
|
||||
constexpr size_t MAX_FOOTPRINTS = 20;
|
||||
constexpr auto FOOTPRINT_SIZE = 64.0f;
|
||||
constexpr int FOOT_HEIGHT_OFFSET = 64;
|
||||
|
||||
struct FOOTPRINT_STRUCT
|
||||
struct Footprint
|
||||
{
|
||||
Vector3 Position[4];
|
||||
bool RightFoot;
|
||||
int Life;
|
||||
int LifeStartFading;
|
||||
float StartOpacity;
|
||||
float Opacity;
|
||||
bool Active;
|
||||
};
|
||||
extern std::deque<FOOTPRINT_STRUCT> footprints;
|
||||
static constexpr auto COUNT_MAX = 64;
|
||||
static constexpr auto VERTEX_COUNT = 4;
|
||||
|
||||
unsigned int SpriteIndex = 0;
|
||||
bool IsRight = false;
|
||||
|
||||
float Life = 0.0f;
|
||||
float LifeStartFading = 0.0f;
|
||||
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 ClearFootprints();
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Environment;
|
||||
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.
|
||||
// Therefore, cannot directly use water status value to determine enrironment.
|
||||
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.
|
||||
CollideSegmentWithRoom(segment, waterHeight, roomNumber, isOnLand);
|
||||
|
@ -161,7 +161,7 @@ namespace TEN::Effects::Hair
|
|||
break;
|
||||
}
|
||||
|
||||
int frameBaseIndex = GetAnimData(animNumber).FramePtr;
|
||||
int frameBaseIndex = GetAnimData(item.ObjectNumber, animNumber).FramePtr;
|
||||
const auto& frame = g_Level.Frames[frameBaseIndex + player.HitFrame];
|
||||
return frame.BoundingBox.GetCenter();
|
||||
}
|
||||
|
|
|
@ -95,17 +95,17 @@ namespace TEN::Effects::Items
|
|||
switch (item->Animation.AnimNumber)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#include "Game/effects/simple_particle.h"
|
||||
|
||||
#include "Game/items.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Environment;
|
||||
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: 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)
|
||||
{
|
||||
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();
|
||||
s = {};
|
||||
s.active = true;
|
||||
s.position = Vector3(x, y, z);
|
||||
s.position = pos;
|
||||
|
||||
Vector3 direction = Vector3(xv, yv, zv);
|
||||
direction.Normalize();
|
||||
auto directionNorm = direction;
|
||||
directionNorm.Normalize();
|
||||
|
||||
s.velocity = direction;
|
||||
s.velocity = directionNorm;
|
||||
s.gravity = -.1f;
|
||||
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, LaraItem);
|
||||
s.sourceColor = Vector4(.4f, .4f, .4f, 1);
|
||||
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, pos.x, pos.y, pos.z, roomNumber);
|
||||
s.sourceColor = Vector4(0.4f, 0.4f, 0.4f, 1);
|
||||
s.destinationColor = Vector4(0, 0, 0, 0);
|
||||
|
||||
if (initial)
|
||||
|
@ -135,7 +140,7 @@ namespace TEN::Effects::Smoke
|
|||
float size = Random::GenerateFloat(48, 80);
|
||||
s.sourceSize = size * 2;
|
||||
s.destinationSize = size * 8;
|
||||
s.sourceColor = {0.75,0.75,1,1};
|
||||
s.sourceColor = { 0.75, 0.75, 1, 1 };
|
||||
s.terminalVelocity = 0;
|
||||
s.friction = 0.82f;
|
||||
s.life = Random::GenerateFloat(60, 90);
|
||||
|
@ -145,7 +150,7 @@ namespace TEN::Effects::Smoke
|
|||
float size = Random::GenerateFloat(48, 80);
|
||||
s.sourceSize = size * 2;
|
||||
s.destinationSize = size * 16;
|
||||
s.velocity = Random::GenerateDirectionInCone(direction, 25);
|
||||
s.velocity = Random::GenerateDirectionInCone(directionNorm, 25);
|
||||
s.velocity *= Random::GenerateFloat(0, 32);
|
||||
}
|
||||
else
|
||||
|
@ -153,7 +158,7 @@ namespace TEN::Effects::Smoke
|
|||
float size = Random::GenerateFloat(48, 80);
|
||||
s.sourceSize = size;
|
||||
s.destinationSize = size * 8;
|
||||
s.velocity = Random::GenerateDirectionInCone(direction, 3);
|
||||
s.velocity = Random::GenerateDirectionInCone(directionNorm, 3);
|
||||
s.velocity *= Random::GenerateFloat(0, 16);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +170,7 @@ namespace TEN::Effects::Smoke
|
|||
s.terminalVelocity = 0;
|
||||
s.friction = 0.88f;
|
||||
s.life = Random::GenerateFloat(60, 90);
|
||||
s.velocity = Random::GenerateDirectionInCone(direction, 10);
|
||||
s.velocity = Random::GenerateDirectionInCone(directionNorm, 10);
|
||||
s.velocity *= Random::GenerateFloat(16, 30);
|
||||
}
|
||||
}
|
||||
|
@ -184,11 +189,11 @@ namespace TEN::Effects::Smoke
|
|||
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.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4);
|
||||
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)
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace TEN::Effects::Smoke
|
|||
void DisableSmokeParticles();
|
||||
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 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 TriggerRocketSmoke(int x, int y, int z);
|
||||
void TriggerBreathSmoke(long x, long y, long z, short angle);
|
||||
|
|
|
@ -15,18 +15,18 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Bubble;
|
||||
using namespace TEN::Effects::Drip;
|
||||
using namespace TEN::Effects::Environment;
|
||||
using namespace TEN::Effects::Ripple;
|
||||
using namespace TEN::Effects::Smoke;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Math;
|
||||
using TEN::Renderer::g_Renderer;
|
||||
|
||||
|
@ -203,14 +203,17 @@ void TriggerGlobalFireFlame()
|
|||
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 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;
|
||||
}
|
||||
|
||||
auto* spark = GetFreeParticle();
|
||||
|
||||
|
@ -229,7 +232,7 @@ void TriggerPilotFlame(int itemNum, int nodeIndex)
|
|||
spark->blendMode = BLEND_MODES::BLENDMODE_ADDITIVE;
|
||||
spark->extras = 0;
|
||||
spark->dynamic = -1;
|
||||
spark->fxObj = itemNum;
|
||||
spark->fxObj = itemNumber;
|
||||
|
||||
spark->x = (GetRandomControl() & 31) - 16;
|
||||
spark->y = (GetRandomControl() & 31) - 16;
|
||||
|
@ -291,7 +294,7 @@ Particle* SetupFireSpark()
|
|||
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);
|
||||
|
||||
|
@ -299,7 +302,7 @@ void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector
|
|||
spark->y = (GetRandomControl() & 0x1F) + pos1.y - 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;
|
||||
|
||||
|
@ -322,32 +325,41 @@ void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector
|
|||
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++)
|
||||
{
|
||||
auto* spark = SetupFireSpark();
|
||||
AttachAndCreateSpark(spark, item, meshIndex, offset, speed);
|
||||
auto& spark = *SetupFireSpark();
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowPoison(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, const Vector3& color)
|
||||
{
|
||||
ThrowPoison(itemNumber, bite.BoneID, bite.Position, vel, color);
|
||||
}
|
||||
|
||||
void UpdateFireProgress()
|
||||
{
|
||||
TriggerGlobalStaticFlame();
|
||||
|
@ -1072,7 +1084,7 @@ void SomeSparkEffect(int x, int y, int z, int count)
|
|||
{
|
||||
auto* spark = GetFreeParticle();
|
||||
|
||||
spark->on = 1;
|
||||
spark->on = true;
|
||||
spark->sR = 112;
|
||||
spark->sG = (GetRandomControl() & 0x1F) + -128;
|
||||
spark->sB = (GetRandomControl() & 0x1F) + -128;
|
||||
|
@ -1109,9 +1121,9 @@ void TriggerUnderwaterExplosion(ItemInfo* item, int flag)
|
|||
TriggerExplosionBubbles(x, y, z, item->RoomNumber);
|
||||
TriggerExplosionSparks(x, y, z, 2, -1, 1, item->RoomNumber);
|
||||
|
||||
int wh = GetWaterHeight(x, y, z, item->RoomNumber);
|
||||
if (wh != NO_HEIGHT)
|
||||
SomeSparkEffect(x, wh, z, 8);
|
||||
int waterHeight = GetWaterHeight(x, y, z, item->RoomNumber);
|
||||
if (waterHeight != NO_HEIGHT)
|
||||
SomeSparkEffect(x, waterHeight, z, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1156,8 +1168,8 @@ void ExplodeVehicle(ItemInfo* laraItem, ItemInfo* vehicle)
|
|||
|
||||
auto* lara = GetLaraInfo(laraItem);
|
||||
|
||||
ExplodingDeath(lara->Vehicle, BODY_EXPLODE | BODY_STONE_SOUND);
|
||||
KillItem(lara->Vehicle);
|
||||
ExplodingDeath(lara->Context.Vehicle, BODY_EXPLODE | BODY_STONE_SOUND);
|
||||
KillItem(lara->Context.Vehicle);
|
||||
vehicle->Status = ITEM_DEACTIVATED;
|
||||
SoundEffect(SFX_TR4_EXPLOSION1, &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->scalar = 3;
|
||||
spark->gravity = 0;
|
||||
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + 13;
|
||||
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_BUBBLES;
|
||||
spark->maxYvel = 0;
|
||||
int size = (GetRandomControl() & 7) + 63;
|
||||
spark->sSize = size >> 1;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Renderer/Renderer11Enums.h"
|
||||
|
||||
enum class LaraWeaponType;
|
||||
struct CreatureBiteInfo;
|
||||
struct ItemInfo;
|
||||
|
||||
enum BodyPartFlags
|
||||
|
@ -232,9 +233,11 @@ int GetFreeFireSpark();
|
|||
void TriggerGlobalStaticFlame();
|
||||
void TriggerGlobalFireSmoke();
|
||||
void TriggerGlobalFireFlame();
|
||||
void TriggerPilotFlame(int itemNum, int nodeIndex);
|
||||
void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed);
|
||||
void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color);
|
||||
void TriggerPilotFlame(int itemNumber, int nodeIndex);
|
||||
void ThrowFire(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel);
|
||||
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 ClearFires();
|
||||
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/tomb4fx.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Random.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Specific/level.h"
|
||||
#include "ScriptInterfaceLevel.h"
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace TEN::Gui
|
|||
constexpr int LINE_HEIGHT = 25;
|
||||
constexpr int PHD_CENTER_X = SCREEN_SPACE_RES.x / 2;
|
||||
constexpr int PHD_CENTER_Y = SCREEN_SPACE_RES.y / 2;
|
||||
constexpr int OBJLIST_SPACING = PHD_CENTER_X / 2;
|
||||
|
||||
constexpr int VOLUME_MAX = 100;
|
||||
|
||||
|
@ -86,6 +87,9 @@ namespace TEN::Gui
|
|||
|
||||
bool GuiController::GuiIsPulsed(ActionID actionID) const
|
||||
{
|
||||
constexpr auto DELAY = 0.1f;
|
||||
constexpr auto INITIAL_DELAY = 0.4f;
|
||||
|
||||
auto oppositeAction = In::None;
|
||||
switch (actionID)
|
||||
{
|
||||
|
@ -107,7 +111,7 @@ namespace TEN::Gui
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -122,16 +126,13 @@ namespace TEN::Gui
|
|||
|
||||
bool GuiController::CanSelect() const
|
||||
{
|
||||
// Holding Deselect safely cancels input.
|
||||
if (IsHeld(In::Deselect))
|
||||
return false;
|
||||
|
||||
if (GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Deselect) &&
|
||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Save) &&
|
||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Load) &&
|
||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Pause))
|
||||
{
|
||||
// Avoid Action release interference when entering inventory.
|
||||
if (GetActionTimeActive(In::Action) < TimeInMenu)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -178,7 +179,11 @@ namespace TEN::Gui
|
|||
|
||||
void GuiController::SetInventoryMode(InventoryMode mode)
|
||||
{
|
||||
InvMode = mode;
|
||||
if (mode != InvMode)
|
||||
{
|
||||
TimeInMenu = 0.0f;
|
||||
InvMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiController::SetInventoryItemChosen(int number)
|
||||
|
@ -228,6 +233,8 @@ namespace TEN::Gui
|
|||
static int selectedOptionBackup;
|
||||
auto inventoryResult = InventoryResult::None;
|
||||
|
||||
TimeInMenu++;
|
||||
|
||||
// Stuff for credits goes here!
|
||||
|
||||
switch (MenuToDisplay)
|
||||
|
@ -281,8 +288,8 @@ namespace TEN::Gui
|
|||
}
|
||||
}
|
||||
else if (MenuToDisplay == Menu::Title ||
|
||||
MenuToDisplay == Menu::SelectLevel ||
|
||||
MenuToDisplay == Menu::Options)
|
||||
MenuToDisplay == Menu::SelectLevel ||
|
||||
MenuToDisplay == Menu::Options)
|
||||
{
|
||||
if (GuiIsPulsed(In::Forward))
|
||||
{
|
||||
|
@ -540,7 +547,7 @@ namespace TEN::Gui
|
|||
|
||||
void GuiController::HandleControlSettingsInput(ItemInfo* item, bool fromPauseMenu)
|
||||
{
|
||||
static const int numControlSettingsOptions = KEY_COUNT + 1;
|
||||
static const int numControlSettingsOptions = KEY_COUNT + 2;
|
||||
|
||||
OptionCount = numControlSettingsOptions;
|
||||
CurrentSettings.WaitingForKey = false;
|
||||
|
@ -554,7 +561,7 @@ namespace TEN::Gui
|
|||
}
|
||||
|
||||
if (GuiIsSelected() &&
|
||||
SelectedOption <= (numControlSettingsOptions - 2))
|
||||
SelectedOption <= (numControlSettingsOptions - 3))
|
||||
{
|
||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||
CurrentSettings.WaitingForKey = true;
|
||||
|
@ -635,6 +642,14 @@ namespace TEN::Gui
|
|||
|
||||
if (GuiIsSelected())
|
||||
{
|
||||
// Defaults.
|
||||
if (SelectedOption == (OptionCount - 2))
|
||||
{
|
||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||
ApplyDefaultBindings();
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply.
|
||||
if (SelectedOption == (OptionCount - 1))
|
||||
{
|
||||
|
@ -888,6 +903,7 @@ namespace TEN::Gui
|
|||
static const int numStatisticsOptions = 0;
|
||||
static const int numOptionsOptions = 2;
|
||||
|
||||
TimeInMenu++;
|
||||
UpdateInputActions(item);
|
||||
|
||||
switch (MenuToDisplay)
|
||||
|
@ -946,7 +962,7 @@ namespace TEN::Gui
|
|||
{
|
||||
if (MenuToDisplay == Menu::Pause)
|
||||
{
|
||||
InvMode = InventoryMode::None;
|
||||
SetInventoryMode(InventoryMode::None);
|
||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||
return InventoryResult::None;
|
||||
}
|
||||
|
@ -979,7 +995,7 @@ namespace TEN::Gui
|
|||
break;
|
||||
|
||||
case PauseMenuOption::ExitToTitle:
|
||||
InvMode = InventoryMode::None;
|
||||
SetInventoryMode(InventoryMode::None);
|
||||
return InventoryResult::ExitToTitle;
|
||||
break;
|
||||
}
|
||||
|
@ -1593,7 +1609,7 @@ namespace TEN::Gui
|
|||
Rings[(int)RingTypes::Ammo]->RingActive = false;
|
||||
}
|
||||
|
||||
void GuiController::InitialiseInventory(ItemInfo* item)
|
||||
void GuiController::InitializeInventory(ItemInfo* item)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
|
||||
|
@ -1603,14 +1619,22 @@ namespace TEN::Gui
|
|||
UseItem = false;
|
||||
|
||||
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite())
|
||||
{
|
||||
Ammo.AmountShotGunAmmo1 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].GetCount() / 6;
|
||||
}
|
||||
|
||||
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].HasInfinite())
|
||||
{
|
||||
Ammo.AmountShotGunAmmo2 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
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.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 (IsItemInInventory(LastInvItem))
|
||||
{
|
||||
SetupObjectListStartPosition(LastInvItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LastInvItem >= INV_OBJECT_SMALL_WATERSKIN_EMPTY && LastInvItem <= INV_OBJECT_SMALL_WATERSKIN_3L)
|
||||
|
@ -1820,7 +1846,7 @@ namespace TEN::Gui
|
|||
ClearAllActions();
|
||||
ActionMap[(int)In::Flare].Update(1.0f);
|
||||
|
||||
HandleWeapon(item);
|
||||
HandleWeapon(*item);
|
||||
ClearAllActions();
|
||||
}
|
||||
|
||||
|
@ -2310,20 +2336,20 @@ namespace TEN::Gui
|
|||
|
||||
case MenuType::Load:
|
||||
// fill_up_savegames_array // Maybe not?
|
||||
InvMode = InventoryMode::Load;
|
||||
SetInventoryMode(InventoryMode::Load);
|
||||
break;
|
||||
|
||||
case MenuType::Save:
|
||||
// fill_up_savegames_array
|
||||
InvMode = InventoryMode::Save;
|
||||
SetInventoryMode(InventoryMode::Save);
|
||||
break;
|
||||
|
||||
case MenuType::Examine:
|
||||
InvMode = InventoryMode::Examine;
|
||||
SetInventoryMode(InventoryMode::Examine);
|
||||
break;
|
||||
|
||||
case MenuType::Statistics:
|
||||
InvMode = InventoryMode::Statistics;
|
||||
SetInventoryMode(InventoryMode::Statistics);
|
||||
break;
|
||||
|
||||
case MenuType::Ammo1:
|
||||
|
@ -2355,7 +2381,7 @@ namespace TEN::Gui
|
|||
break;
|
||||
|
||||
case MenuType::Diary:
|
||||
InvMode = InventoryMode::Diary;
|
||||
SetInventoryMode(InventoryMode::Diary);
|
||||
lara->Inventory.Diary.CurrentPage = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -2918,9 +2944,9 @@ namespace TEN::Gui
|
|||
g_Renderer.DumpGameScene();
|
||||
|
||||
if (resetMode)
|
||||
InvMode = InventoryMode::InGame;
|
||||
SetInventoryMode(InventoryMode::InGame);
|
||||
|
||||
InitialiseInventory(item);
|
||||
InitializeInventory(item);
|
||||
Camera.numberFrames = 2;
|
||||
|
||||
bool exitLoop = false;
|
||||
|
@ -2929,10 +2955,10 @@ namespace TEN::Gui
|
|||
if (ThreadEnded)
|
||||
return false;
|
||||
|
||||
OBJLIST_SPACING = PHD_CENTER_X / 2;
|
||||
TimeInMenu++;
|
||||
GameTimer++;
|
||||
|
||||
UpdateInputActions(item);
|
||||
GameTimer++;
|
||||
|
||||
if (IsClicked(In::Option))
|
||||
{
|
||||
|
@ -2973,7 +2999,7 @@ namespace TEN::Gui
|
|||
exitLoop = !resetMode;
|
||||
|
||||
if (resetMode)
|
||||
InvMode = InventoryMode::InGame;
|
||||
SetInventoryMode(InventoryMode::InGame);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -2988,7 +3014,7 @@ namespace TEN::Gui
|
|||
{
|
||||
exitLoop = !resetMode;
|
||||
if (resetMode)
|
||||
InvMode = InventoryMode::InGame;
|
||||
SetInventoryMode(InventoryMode::InGame);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -3011,30 +3037,30 @@ namespace TEN::Gui
|
|||
AlterFOV(LastFOV);
|
||||
|
||||
lara->Inventory.IsBusy = lara->Inventory.OldBusy;
|
||||
InvMode = InventoryMode::None;
|
||||
SetInventoryMode(InventoryMode::None);
|
||||
|
||||
return doLoad;
|
||||
}
|
||||
|
||||
void GuiController::DoStatisticsMode()
|
||||
{
|
||||
InvMode = InventoryMode::Statistics;
|
||||
SetInventoryMode(InventoryMode::Statistics);
|
||||
|
||||
if (GuiIsDeselected())
|
||||
{
|
||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||
InvMode = InventoryMode::InGame;
|
||||
SetInventoryMode(InventoryMode::InGame);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiController::DoExamineMode()
|
||||
{
|
||||
this->InvMode = InventoryMode::Examine;
|
||||
SetInventoryMode(InventoryMode::Examine);
|
||||
|
||||
if (GuiIsDeselected())
|
||||
{
|
||||
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);
|
||||
|
||||
this->InvMode = InventoryMode::Diary;
|
||||
SetInventoryMode(InventoryMode::Diary);
|
||||
|
||||
if (GuiIsPulsed(In::Right) &&
|
||||
lara->Inventory.Diary.CurrentPage < lara->Inventory.Diary.NumPages)
|
||||
|
@ -3075,7 +3101,7 @@ namespace TEN::Gui
|
|||
if (GuiIsDeselected())
|
||||
{
|
||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||
InvMode = InventoryMode::None;
|
||||
SetInventoryMode(InventoryMode::None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ namespace TEN::Gui
|
|||
int OptionCount;
|
||||
int SelectedSaveSlot;
|
||||
|
||||
float TimeInMenu = 0.0f;
|
||||
SettingsData CurrentSettings;
|
||||
|
||||
// Inventory variables
|
||||
|
@ -150,7 +151,6 @@ namespace TEN::Gui
|
|||
short NormalRingFadeVal;
|
||||
short NormalRingFadeDir;
|
||||
unsigned char AmmoActive;
|
||||
int OBJLIST_SPACING;
|
||||
MenuOption CurrentOptions[3];
|
||||
InventoryMode InvMode;
|
||||
int InventoryItemChosen;
|
||||
|
@ -199,7 +199,7 @@ namespace TEN::Gui
|
|||
void HandleOptionsInput();
|
||||
void BackupOptions();
|
||||
bool DoObjectsCombine(int objectNumber1, int objectNumber2);
|
||||
void InitialiseInventory(ItemInfo* item);
|
||||
void InitializeInventory(ItemInfo* item);
|
||||
void FillDisplayOptions();
|
||||
bool IsItemCurrentlyCombinable(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
|
||||
{
|
||||
bool Initialised = false;
|
||||
bool Initialized = false;
|
||||
|
||||
std::vector<BoxNode> Node = {};
|
||||
int Head = 0;
|
||||
|
@ -71,6 +71,62 @@ struct LOTInfo
|
|||
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
|
||||
{
|
||||
int ItemNumber = -1;
|
||||
|
@ -96,11 +152,13 @@ struct CreatureInfo
|
|||
bool MonkeySwingAhead = false;
|
||||
bool ReachedGoal = false;
|
||||
|
||||
short FiredWeapon = 0;
|
||||
CreatureMuzzleFlashInfo MuzzleFlash[2];
|
||||
short Tosspad = 0;
|
||||
short LocationAI = 0;
|
||||
short Flags = 0;
|
||||
|
||||
bool IsTargetAlive();
|
||||
|
||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||
CreatureAIPriority Priority = CreatureAIPriority::None;
|
||||
size_t FramesSinceLOTUpdate = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "framework.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/motorbike_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"
|
||||
|
||||
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::Generic;
|
||||
using namespace TEN::Entities::TR4;
|
||||
using namespace TEN::Entities::Vehicles;
|
||||
|
||||
struct ItemInfo;
|
||||
|
||||
class ITEM_DATA
|
||||
class ItemData
|
||||
{
|
||||
std::variant<
|
||||
std::nullptr_t,
|
||||
|
@ -67,16 +68,17 @@ class ITEM_DATA
|
|||
UPVInfo,
|
||||
SpeedboatInfo,
|
||||
RubberBoatInfo,
|
||||
MinecartInfo
|
||||
MinecartInfo,
|
||||
ElectricalLightInfo
|
||||
> data;
|
||||
public:
|
||||
ITEM_DATA();
|
||||
ItemData();
|
||||
|
||||
template<typename D>
|
||||
ITEM_DATA(D&& type) : data(std::move(type)) {}
|
||||
ItemData(D&& type) : data(std::move(type)) {}
|
||||
|
||||
// conversion operators to keep original syntax!
|
||||
// TODO: should be removed later and
|
||||
// Conversion operators to keep original syntax.
|
||||
// TODO: Should be removed later and use polymorphism instead.
|
||||
template<typename T>
|
||||
operator T* ()
|
||||
{
|
||||
|
@ -86,7 +88,7 @@ class ITEM_DATA
|
|||
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>
|
||||
|
@ -98,33 +100,33 @@ class ITEM_DATA
|
|||
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>
|
||||
ITEM_DATA& operator=(T* newData)
|
||||
ItemData& operator =(T* newData)
|
||||
{
|
||||
data = *newData;
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
|
||||
ITEM_DATA& operator=(std::nullptr_t null)
|
||||
ItemData& operator =(std::nullptr_t null)
|
||||
{
|
||||
data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ITEM_DATA& operator=(T& newData)
|
||||
ItemData& operator =(T& newData)
|
||||
{
|
||||
data = newData;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ITEM_DATA& operator=(T&& newData)
|
||||
ItemData& operator =(T&& newData)
|
||||
{
|
||||
data = std::move(newData);
|
||||
return *this;
|
||||
|
@ -139,12 +141,12 @@ class ITEM_DATA
|
|||
void apply(Funcs&&... funcs)
|
||||
{
|
||||
std::visit(
|
||||
visitor
|
||||
visitor
|
||||
{
|
||||
[](auto const&) {},
|
||||
std::forward<Funcs>(funcs)...
|
||||
},
|
||||
data);
|
||||
data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/savegame.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
||||
#include "Scripting/Include/ScriptInterfaceGame.h"
|
||||
|
@ -17,12 +18,11 @@
|
|||
#include "Specific/clock.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Scripting/Internal/TEN/Objects/ObjectIDs.h"
|
||||
|
||||
using namespace TEN::Control::Volumes;
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Input;
|
||||
using namespace TEN::Math;
|
||||
|
||||
|
@ -144,10 +144,10 @@ bool ItemInfo::IsCreature() const
|
|||
|
||||
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++)
|
||||
this->Model.MeshIndex[i] = this->Model.BaseMesh + i;
|
||||
for (int i = 0; i < Model.MeshIndex.size(); i++)
|
||||
Model.MeshIndex[i] = Model.BaseMesh + i;
|
||||
}
|
||||
|
||||
bool TestState(int refState, const vector<int>& stateList)
|
||||
|
@ -196,7 +196,9 @@ void KillItem(short const itemNumber)
|
|||
item->Active = false;
|
||||
|
||||
if (NextItemActive == itemNumber)
|
||||
{
|
||||
NextItemActive = item->NextActive;
|
||||
}
|
||||
else
|
||||
{
|
||||
short linkNumber;
|
||||
|
@ -213,7 +215,9 @@ void KillItem(short const itemNumber)
|
|||
if (item->RoomNumber != NO_ROOM)
|
||||
{
|
||||
if (g_Level.Rooms[item->RoomNumber].itemNumber == itemNumber)
|
||||
{
|
||||
g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
short linkNumber;
|
||||
|
@ -229,7 +233,7 @@ void KillItem(short const itemNumber)
|
|||
}
|
||||
|
||||
if (item == Lara.TargetEntity)
|
||||
Lara.TargetEntity = NULL;
|
||||
Lara.TargetEntity = nullptr;
|
||||
|
||||
if (Objects[item->ObjectNumber].floor != nullptr)
|
||||
UpdateBridgeItem(itemNumber, true);
|
||||
|
@ -242,7 +246,9 @@ void KillItem(short const itemNumber)
|
|||
NextItemFree = itemNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->Flags |= IFLAG_KILLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,7 +428,7 @@ short CreateNewEffect(short roomNumber)
|
|||
return fxNumber;
|
||||
}
|
||||
|
||||
void InitialiseFXArray(int allocateMemory)
|
||||
void InitializeFXArray(int allocateMemory)
|
||||
{
|
||||
NextFxActive = NO_ITEM;
|
||||
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];
|
||||
|
||||
item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex;
|
||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
||||
|
||||
SetAnimation(item, 0);
|
||||
item->Animation.RequiredState = NO_STATE;
|
||||
item->Animation.TargetState = g_Level.Anims[item->Animation.AnimNumber].ActiveState;
|
||||
item->Animation.ActiveState = g_Level.Anims[item->Animation.AnimNumber].ActiveState;
|
||||
|
||||
item->Animation.Velocity.y = 0;
|
||||
item->Animation.Velocity.z = 0;
|
||||
item->Animation.Velocity = Vector3::Zero;
|
||||
|
||||
for (int i = 0; i < NUM_ITEM_FLAGS; i++)
|
||||
item->ItemFlags[i] = 0;
|
||||
|
@ -516,7 +516,9 @@ void InitialiseItem(short itemNumber)
|
|||
item->MeshBits = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->MeshBits = ALL_JOINT_BITS;
|
||||
}
|
||||
|
||||
item->TouchBits = NO_JOINT_BITS;
|
||||
item->AfterDeath = 0;
|
||||
|
@ -527,7 +529,9 @@ void InitialiseItem(short itemNumber)
|
|||
item->Status = ITEM_INVISIBLE;
|
||||
}
|
||||
else if (Objects[item->ObjectNumber].intelligent)
|
||||
{
|
||||
item->Status = ITEM_INVISIBLE;
|
||||
}
|
||||
|
||||
if ((item->Flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
|
||||
{
|
||||
|
@ -560,8 +564,8 @@ void InitialiseItem(short itemNumber)
|
|||
item->Model.MeshIndex.clear();
|
||||
}
|
||||
|
||||
if (Objects[item->ObjectNumber].initialise != nullptr)
|
||||
Objects[item->ObjectNumber].initialise(itemNumber);
|
||||
if (Objects[item->ObjectNumber].Initialize != nullptr)
|
||||
Objects[item->ObjectNumber].Initialize(itemNumber);
|
||||
}
|
||||
|
||||
short CreateItem()
|
||||
|
@ -576,7 +580,7 @@ short CreateItem()
|
|||
return itemNumber;
|
||||
}
|
||||
|
||||
void InitialiseItemArray(int totalItem)
|
||||
void InitializeItemArray(int totalItem)
|
||||
{
|
||||
g_Level.Items.clear();
|
||||
g_Level.Items.resize(totalItem);
|
||||
|
@ -612,7 +616,7 @@ short SpawnItem(ItemInfo* item, GAME_OBJECT_ID objectNumber)
|
|||
spawn->RoomNumber = item->RoomNumber;
|
||||
memcpy(&spawn->Pose, &item->Pose, sizeof(Pose));
|
||||
|
||||
InitialiseItem(itemNumber);
|
||||
InitializeItem(itemNumber);
|
||||
|
||||
spawn->Status = ITEM_NOT_ACTIVE;
|
||||
spawn->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
|
||||
#include "Game/animation.h"
|
||||
#include "Game/itemdata/itemdata.h"
|
||||
#include "Objects/game_object_ids.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/newtypes.h"
|
||||
#include "Specific/BitField.h"
|
||||
|
||||
using namespace TEN::Utils;
|
||||
|
||||
enum GAME_OBJECT_ID : short;
|
||||
|
||||
constexpr auto NO_ITEM = -1;
|
||||
constexpr auto NOT_TARGETABLE = -16384;
|
||||
|
||||
|
@ -66,6 +65,8 @@ enum class EffectType
|
|||
|
||||
struct EntityAnimationData
|
||||
{
|
||||
GAME_OBJECT_ID AnimObjectID = ID_NO_OBJECT;
|
||||
|
||||
int AnimNumber = 0; // g_Level.Anims index.
|
||||
int FrameNumber = 0; // g_Level.Frames index.
|
||||
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
|
||||
struct ItemInfo
|
||||
{
|
||||
GAME_OBJECT_ID ObjectNumber;
|
||||
std::string Name;
|
||||
GAME_OBJECT_ID ObjectNumber = ID_NO_OBJECT; // ObjectID
|
||||
std::string Name = {};
|
||||
|
||||
int Status; // ItemStatus enum.
|
||||
bool Active;
|
||||
|
@ -116,7 +117,7 @@ struct ItemInfo
|
|||
short NextItem;
|
||||
short NextActive;
|
||||
|
||||
ITEM_DATA Data;
|
||||
ItemData Data;
|
||||
EntityAnimationData Animation;
|
||||
EntityCallbackData Callbacks;
|
||||
EntityModelData Model;
|
||||
|
@ -178,11 +179,11 @@ short CreateItem();
|
|||
void RemoveAllItemsInRoom(short roomNumber, short objectNumber);
|
||||
void RemoveActiveItem(short itemNumber, bool killed = true);
|
||||
void RemoveDrawnItem(short itemNumber);
|
||||
void InitialiseFXArray(int allocateMemory);
|
||||
void InitializeFXArray(int allocateMemory);
|
||||
short CreateNewEffect(short roomNumber);
|
||||
void KillEffect(short fxNumber);
|
||||
void InitialiseItem(short itemNumber);
|
||||
void InitialiseItemArray(int totalItems);
|
||||
void InitializeItem(short itemNumber);
|
||||
void InitializeItemArray(int totalItems);
|
||||
void KillItem(short itemNumber);
|
||||
bool UpdateItemRoom(short itemNumber);
|
||||
void UpdateAllItems();
|
||||
|
@ -195,3 +196,4 @@ int FindItem(ItemInfo* item);
|
|||
void DoDamage(ItemInfo* item, int damage);
|
||||
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);
|
||||
short SpawnItem(ItemInfo* item, GAME_OBJECT_ID objectNumber);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "Game/Lara/lara.h"
|
||||
#include "Game/itemdata/creature_info.h"
|
||||
#include "Game/items.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
using std::vector;
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
#include "Game/effects/Bubble.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Bubble;
|
||||
using namespace TEN::Effects::Explosion;
|
||||
|
@ -115,7 +115,7 @@ void ControlMissile(short fxNumber)
|
|||
EffectNewRoom(fxNumber, pointColl.RoomNumber);
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "Game/misc.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* 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)
|
||||
{
|
||||
// TODO: Remove -128 and fix ricochet effect going on floor. -- TokyoSU 2023.04.28
|
||||
auto pos = GameVector(
|
||||
LaraItem->Pose.Position.x + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||
LaraItem->Floor,
|
||||
LaraItem->Floor - 128,
|
||||
LaraItem->Pose.Position.z + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||
LaraItem->RoomNumber);
|
||||
|
||||
Ricochet(Pose(pos.x, pos.y, pos.z));
|
||||
Ricochet(Pose(pos.ToVector3i()));
|
||||
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;
|
||||
}
|
||||
|
||||
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())
|
||||
// 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;
|
||||
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
|
@ -134,9 +135,9 @@ bool Targetable(ItemInfo* item, AI_INFO* AI)
|
|||
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;
|
||||
|
||||
// Check just in case.
|
||||
|
@ -148,7 +149,7 @@ bool TargetVisible(ItemInfo* item, AI_INFO* AI, float maxAngleInDegrees)
|
|||
if (enemy == nullptr || enemy->HitPoints == 0)
|
||||
return false;
|
||||
|
||||
short angle = AI->angle - creature->JointRotation[2];
|
||||
short angle = ai->angle - creature->JointRotation[2];
|
||||
if (angle > ANGLE(-maxAngleInDegrees) && angle < ANGLE(maxAngleInDegrees))
|
||||
{
|
||||
const auto& bounds = GetBestFrame(*enemy).BoundingBox;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#pragma once
|
||||
#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 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);
|
||||
bool Targetable(ItemInfo* item, AI_INFO* AI);
|
||||
bool TargetVisible(ItemInfo* item, AI_INFO* AI, float maxAngleInDegrees = 45.0f);
|
||||
bool Targetable(ItemInfo* item, AI_INFO* ai);
|
||||
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_weapon.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Generic/Object/burning_torch.h"
|
||||
#include "Objects/TR4/Object/tr4_clockwork_beetle.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/setup.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
|
||||
using namespace TEN::Entities::Generic;
|
||||
|
@ -273,10 +273,10 @@ void DoPickup(ItemInfo* laraItem)
|
|||
{
|
||||
auto* lara = GetLaraInfo(laraItem);
|
||||
|
||||
if (lara->InteractedItem == NO_ITEM)
|
||||
if (lara->Context.InteractedItem == NO_ITEM)
|
||||
return;
|
||||
|
||||
short pickupItemNumber = lara->InteractedItem;
|
||||
short pickupItemNumber = lara->Context.InteractedItem;
|
||||
auto* pickupItem = &g_Level.Items[pickupItemNumber];
|
||||
|
||||
if (!Objects[pickupItem->ObjectNumber].isPickup)
|
||||
|
@ -292,7 +292,7 @@ void DoPickup(ItemInfo* laraItem)
|
|||
|
||||
KillItem(pickupItemNumber);
|
||||
pickupItem->Pose.Orientation = prevOrient;
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
else if (pickupItem->ObjectNumber == ID_FLARE_ITEM)
|
||||
|
@ -301,25 +301,25 @@ void DoPickup(ItemInfo* laraItem)
|
|||
{
|
||||
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
||||
InitialiseNewWeapon(laraItem);
|
||||
InitializeNewWeapon(*laraItem);
|
||||
lara->Control.HandStatus = HandStatus::Special;
|
||||
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
||||
DrawFlareMeshes(laraItem);
|
||||
DrawFlareMeshes(*laraItem);
|
||||
KillItem(pickupItemNumber);
|
||||
|
||||
pickupItem->Pose.Orientation = prevOrient;
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
else if (laraItem->Animation.ActiveState == LS_PICKUP_FLARE)
|
||||
{
|
||||
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
||||
InitialiseNewWeapon(laraItem);
|
||||
InitializeNewWeapon(*laraItem);
|
||||
lara->Control.HandStatus = HandStatus::Special;
|
||||
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
||||
KillItem(pickupItemNumber);
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -330,8 +330,8 @@ void DoPickup(ItemInfo* laraItem)
|
|||
{
|
||||
if (g_GameFlow->IsMassPickupEnabled())
|
||||
{
|
||||
CollectMultiplePickups(lara->InteractedItem);
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
CollectMultiplePickups(lara->Context.InteractedItem);
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ void DoPickup(ItemInfo* laraItem)
|
|||
}
|
||||
|
||||
pickupItem->Pose.Orientation = prevOrient;
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -365,8 +365,8 @@ void DoPickup(ItemInfo* laraItem)
|
|||
{
|
||||
if (g_GameFlow->IsMassPickupEnabled())
|
||||
{
|
||||
CollectMultiplePickups(lara->InteractedItem);
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
CollectMultiplePickups(lara->Context.InteractedItem);
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -389,13 +389,13 @@ void DoPickup(ItemInfo* laraItem)
|
|||
|
||||
pickupItem->Pose.Orientation = prevOrient;
|
||||
KillItem(pickupItemNumber);
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lara->InteractedItem = NO_ITEM;
|
||||
lara->Context.InteractedItem = NO_ITEM;
|
||||
}
|
||||
|
||||
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 &&
|
||||
laraItem->Animation.ActiveState == LS_UNDERWATER_IDLE &&
|
||||
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))
|
||||
{
|
||||
|
@ -454,13 +454,13 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
lara->Control.HandStatus = HandStatus::Busy;
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lara->Control.IsMoving)
|
||||
{
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
|
@ -486,7 +486,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
{
|
||||
if (!lara->Control.IsMoving)
|
||||
{
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
|
@ -519,7 +519,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
{
|
||||
if (lara->Control.IsMoving)
|
||||
{
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
|
@ -536,7 +536,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
flag = true;
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
|
||||
// Pick up with crowbar.
|
||||
|
@ -551,7 +551,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
return;
|
||||
}
|
||||
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
|
@ -590,7 +590,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
flag = true;
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
|
||||
// Pick up from plinth.
|
||||
|
@ -642,7 +642,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
flag = true;
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -652,7 +652,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
return;
|
||||
}
|
||||
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
|
@ -679,7 +679,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
flag = true;
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
|
||||
// Pick up from ground.
|
||||
|
@ -692,7 +692,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
return;
|
||||
}
|
||||
|
||||
if (lara->InteractedItem == itemNumber)
|
||||
if (lara->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
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.ActiveState = LS_PICKUP_FLARE;
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
@ -741,14 +741,14 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
{
|
||||
laraItem->Animation.TargetState = LS_PICKUP;
|
||||
}
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!MoveLaraPosition(PickUpPosition, item, laraItem))
|
||||
{
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -756,7 +756,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
{
|
||||
laraItem->Animation.AnimNumber = LA_PICKUP;
|
||||
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
@ -769,14 +769,14 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
}
|
||||
}
|
||||
|
||||
lara->InteractedItem = itemNumber;
|
||||
lara->Context.InteractedItem = itemNumber;
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||
ResetLaraFlex(laraItem);
|
||||
ResetPlayerFlex(laraItem);
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Busy;
|
||||
}
|
||||
|
@ -1071,7 +1071,7 @@ GameBoundingBox* FindPlinth(ItemInfo* item)
|
|||
return &GetBestFrame(g_Level.Items[itemNumber]).BoundingBox;
|
||||
}
|
||||
|
||||
void InitialisePickup(short itemNumber)
|
||||
void InitializePickup(short 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];
|
||||
if (item->ObjectNumber == ID_SEARCH_OBJECT1)
|
||||
|
@ -1183,7 +1183,7 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
|||
laraItem->Animation.AnimNumber == LA_STAND_IDLE &&
|
||||
lara->Control.HandStatus == HandStatus::Free &&
|
||||
((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);
|
||||
if (item->ObjectNumber != ID_SEARCH_OBJECT1)
|
||||
|
@ -1205,7 +1205,7 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
|||
{
|
||||
if (MoveLaraPosition(SOPos, item, laraItem))
|
||||
{
|
||||
ResetLaraFlex(laraItem);
|
||||
ResetPlayerFlex(laraItem);
|
||||
laraItem->Animation.AnimNumber = SearchAnims[objectNumber];
|
||||
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||
laraItem->Animation.ActiveState = LS_MISC_CONTROL;
|
||||
|
@ -1225,9 +1225,9 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
|||
AnimateItem(item);
|
||||
}
|
||||
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.HandStatus = HandStatus::Free;
|
||||
|
@ -1363,7 +1363,7 @@ bool UseSpecialItem(ItemInfo* laraItem)
|
|||
|
||||
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)
|
||||
lara->Inventory.SmallWaterskin = 4;
|
||||
|
|
|
@ -10,7 +10,7 @@ extern int NumRPickups;
|
|||
extern short RPickups[16];
|
||||
extern Vector3i OldPickupPos;
|
||||
|
||||
void InitialisePickup(short itemNumber);
|
||||
void InitializePickup(short itemNumber);
|
||||
bool SetInventoryCount(GAME_OBJECT_ID objectID, int count);
|
||||
void PickedUpObject(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 InitialiseSearchObject(short itemNumber);
|
||||
void InitializeSearchObject(short itemNumber);
|
||||
void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
|
||||
void SearchObjectControl(short itemNumber);
|
||||
void DoPickup(ItemInfo* laraItem);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "Game/items.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
|
||||
using namespace TEN::Floordata;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Renderer;
|
||||
|
||||
byte FlipStatus = 0;
|
||||
|
|
|
@ -1,11 +1,43 @@
|
|||
#pragma once
|
||||
#include "framework.h"
|
||||
#include "Game/collision/floordata.h"
|
||||
#include "Specific/newtypes.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Specific/newtypes.h"
|
||||
|
||||
struct TriggerVolume;
|
||||
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
|
||||
{
|
||||
|
@ -13,8 +45,8 @@ struct ROOM_VERTEX
|
|||
Vector3 normal;
|
||||
Vector2 textureCoordinates;
|
||||
Vector3 color;
|
||||
int effects;
|
||||
int index;
|
||||
int effects;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct ROOM_DOOR
|
||||
|
@ -53,44 +85,22 @@ struct MESH_INFO
|
|||
|
||||
struct LIGHTINFO
|
||||
{
|
||||
int x; // size=0, offset=0
|
||||
int y; // size=0, offset=4
|
||||
int z; // size=0, offset=8
|
||||
unsigned char Type; // size=0, offset=12
|
||||
unsigned char r; // size=0, offset=13
|
||||
unsigned char g; // size=0, offset=14
|
||||
unsigned char b; // size=0, offset=15
|
||||
short nx; // size=0, offset=16
|
||||
short ny; // size=0, offset=18
|
||||
short nz; // size=0, offset=20
|
||||
short Intensity; // size=0, offset=22
|
||||
unsigned char Inner; // size=0, offset=24
|
||||
unsigned char Outer; // size=0, offset=25
|
||||
short FalloffScale; // size=0, offset=26
|
||||
short Length; // size=0, offset=28
|
||||
short Cutoff; // size=0, offset=30
|
||||
};
|
||||
|
||||
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
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
unsigned char Type;
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
short nx;
|
||||
short ny;
|
||||
short nz;
|
||||
short Intensity;
|
||||
unsigned char Inner;
|
||||
unsigned char Outer;
|
||||
short FalloffScale;
|
||||
short Length;
|
||||
short Cutoff;
|
||||
};
|
||||
|
||||
struct ROOM_INFO
|
||||
|
@ -113,36 +123,26 @@ struct ROOM_INFO
|
|||
short fxNumber;
|
||||
bool boundActive;
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> tags;
|
||||
std::string name = {};
|
||||
std::vector<std::string> tags = {};
|
||||
|
||||
std::vector<FloorInfo> floor;
|
||||
std::vector<ROOM_LIGHT> lights;
|
||||
std::vector<MESH_INFO> mesh;
|
||||
std::vector<TriggerVolume> triggerVolumes;
|
||||
std::vector<FloorInfo> floor = {};
|
||||
std::vector<ROOM_LIGHT> lights = {};
|
||||
std::vector<MESH_INFO> mesh = {};
|
||||
std::vector<TriggerVolume> triggerVolumes = {};
|
||||
|
||||
std::vector<Vector3> positions;
|
||||
std::vector<Vector3> normals;
|
||||
std::vector<Vector3> colors;
|
||||
std::vector<Vector3> effects;
|
||||
std::vector<BUCKET> buckets;
|
||||
std::vector<ROOM_DOOR> doors;
|
||||
std::vector<Vector3> positions = {};
|
||||
std::vector<Vector3> normals = {};
|
||||
std::vector<Vector3> colors = {};
|
||||
std::vector<Vector3> effects = {};
|
||||
std::vector<BUCKET> buckets = {};
|
||||
std::vector<ROOM_DOOR> doors = {};
|
||||
|
||||
std::vector<int> neighbors; // TODO: Move to level struct
|
||||
std::vector<int> neighbors = {};
|
||||
|
||||
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 AddRoomFlipItems(ROOM_INFO* room);
|
||||
void RemoveRoomFlipItems(ROOM_INFO* room);
|
||||
|
|
|
@ -18,31 +18,30 @@
|
|||
#include "Game/misc.h"
|
||||
#include "Game/spotcam.h"
|
||||
#include "Game/room.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Objects/Generic/Object/rope.h"
|
||||
#include "Objects/Generic/Switches/fullblock_switch.h"
|
||||
#include "Objects/Generic/Traps/traps.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/Sink.h"
|
||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||
#include "Objects/TR5/Emitter/tr5_rats_emitter.h"
|
||||
#include "Objects/TR5/Emitter/tr5_bats_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 "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/setup.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::Entities::Generic;
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Entities::Switches;
|
||||
using namespace TEN::Entities::TR4;
|
||||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Floordata;
|
||||
using namespace flatbuffers;
|
||||
|
||||
namespace Save = TEN::Save;
|
||||
|
||||
|
@ -80,7 +79,7 @@ void LoadSavegameInfos()
|
|||
}
|
||||
}
|
||||
|
||||
Pose ToPHD(Save::Position const* src)
|
||||
Pose ToPHD(const Save::Position* src)
|
||||
{
|
||||
Pose dest;
|
||||
dest.Position.x = src->x_pos();
|
||||
|
@ -92,9 +91,10 @@ Pose ToPHD(Save::Position const* src)
|
|||
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.y,
|
||||
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)
|
||||
{
|
||||
return Save::Vector3(vec.x, vec.y, vec.z);
|
||||
|
@ -126,12 +131,17 @@ Save::Vector4 FromVector4(Vector4 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)
|
||||
{
|
||||
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)
|
||||
|
@ -149,10 +159,10 @@ Vector4 ToVector4(const Save::Vector4* vec)
|
|||
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); \
|
||||
TableBuilder vtb{ fbb }; \
|
||||
Save::Vector3 saveVec = FromVector3(data); \
|
||||
SaveType saveVec = ConversionFunc(data); \
|
||||
vtb.add_vec(&saveVec); \
|
||||
auto vecOffset = vtb.Finish(); \
|
||||
putDataInVec(UnionType, vecOffset);
|
||||
|
@ -389,7 +399,7 @@ bool SaveGame::Save(int slot)
|
|||
Save::LaraControlDataBuilder control{ fbb };
|
||||
control.add_move_angle(Lara.Control.MoveAngle);
|
||||
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_hand_status((int)Lara.Control.HandStatus);
|
||||
control.add_is_moving(Lara.Control.IsMoving);
|
||||
|
@ -452,7 +462,7 @@ bool SaveGame::Save(int slot)
|
|||
|
||||
Save::LaraBuilder lara{ fbb };
|
||||
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_extra_anim(Lara.ExtraAnim);
|
||||
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_hit_direction(Lara.HitDirection);
|
||||
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_item_number(Lara.ItemNumber);
|
||||
lara.add_left_arm(leftArmOffset);
|
||||
lara.add_location(Lara.Location);
|
||||
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_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_entity_number(Lara.TargetEntity - g_Level.Items.data());
|
||||
lara.add_torch(torchOffset);
|
||||
lara.add_vehicle(Lara.Vehicle);
|
||||
lara.add_water_current_active(Lara.WaterCurrentActive);
|
||||
lara.add_water_current_pull(&FromVector3(Lara.WaterCurrentPull));
|
||||
lara.add_water_surface_dist(Lara.WaterSurfaceDist);
|
||||
lara.add_vehicle(Lara.Context.Vehicle);
|
||||
lara.add_water_current_active(Lara.Context.WaterCurrentActive);
|
||||
lara.add_water_current_pull(&FromVector3(Lara.Context.WaterCurrentPull));
|
||||
lara.add_water_surface_dist(Lara.Context.WaterSurfaceDist);
|
||||
lara.add_weapons(carriedWeaponsOffset);
|
||||
auto laraOffset = lara.Finish();
|
||||
|
||||
|
@ -527,8 +537,7 @@ bool SaveGame::Save(int slot)
|
|||
flatbuffers::Offset<Save::Short> shortOffset;
|
||||
flatbuffers::Offset<Save::Int> intOffset;
|
||||
|
||||
if (Objects[itemToSerialize.ObjectNumber].intelligent
|
||||
&& itemToSerialize.Data.is<CreatureInfo>())
|
||||
if (Objects[itemToSerialize.ObjectNumber].intelligent && itemToSerialize.IsCreature())
|
||||
{
|
||||
auto creature = GetCreatureInfo(&itemToSerialize);
|
||||
|
||||
|
@ -538,12 +547,10 @@ bool SaveGame::Save(int slot)
|
|||
auto jointRotationsOffset = fbb.CreateVector(jointRotations);
|
||||
|
||||
Save::CreatureBuilder creatureBuilder{ fbb };
|
||||
|
||||
creatureBuilder.add_alerted(creature->Alerted);
|
||||
creatureBuilder.add_can_jump(creature->LOT.CanJump);
|
||||
creatureBuilder.add_can_monkey(creature->LOT.CanMonkey);
|
||||
creatureBuilder.add_enemy(creature->Enemy - g_Level.Items.data());
|
||||
creatureBuilder.add_fired_weapon(creature->FiredWeapon);
|
||||
creatureBuilder.add_flags(creature->Flags);
|
||||
creatureBuilder.add_friendly(creature->Friendly);
|
||||
creatureBuilder.add_head_left(creature->HeadLeft);
|
||||
|
@ -555,6 +562,8 @@ bool SaveGame::Save(int slot)
|
|||
creatureBuilder.add_joint_rotation(jointRotationsOffset);
|
||||
creatureBuilder.add_jump_ahead(creature->JumpAhead);
|
||||
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_monkey_swing_ahead(creature->MonkeySwingAhead);
|
||||
creatureBuilder.add_mood((int)creature->Mood);
|
||||
|
@ -1164,16 +1173,24 @@ bool SaveGame::Save(int slot)
|
|||
{
|
||||
switch (SavedVarType(s.index()))
|
||||
{
|
||||
case SavedVarType::Vec2:
|
||||
{
|
||||
SaveVec(SavedVarType::Vec2, s, Save::vec2TableBuilder, Save::VarUnion::vec2, Save::Vector2, FromVector2);
|
||||
}
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
case SavedVarType::Color:
|
||||
{
|
||||
Save::colorTableBuilder ctb{ fbb };
|
||||
|
@ -1183,18 +1200,51 @@ bool SaveGame::Save(int slot)
|
|||
putDataInVec(Save::VarUnion::color, offset);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto unionVec = fbb.CreateVector(varsVec);
|
||||
Save::UnionVecBuilder uvb{ fbb };
|
||||
uvb.add_members(unionVec);
|
||||
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> 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 stringsCallbackPostControl = fbb.CreateVectorOfStrings(callbackVecPostControl);
|
||||
|
||||
|
@ -1243,6 +1293,19 @@ bool SaveGame::Save(int slot)
|
|||
}
|
||||
|
||||
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_post_control(stringsCallbackPostControl);
|
||||
|
||||
|
@ -1543,20 +1606,25 @@ bool SaveGame::Load(int slot)
|
|||
creature->Alerted = savedCreature->alerted();
|
||||
creature->LOT.CanJump = savedCreature->can_jump();
|
||||
creature->LOT.CanMonkey = savedCreature->can_monkey();
|
||||
|
||||
if (savedCreature->enemy() >= 0)
|
||||
creature->Enemy = &g_Level.Items[savedCreature->enemy()];
|
||||
creature->FiredWeapon = savedCreature->fired_weapon();
|
||||
|
||||
creature->Flags = savedCreature->flags();
|
||||
creature->Friendly = savedCreature->friendly();
|
||||
creature->HeadLeft = savedCreature->head_left();
|
||||
creature->HeadRight = savedCreature->head_right();
|
||||
creature->HurtByLara = savedCreature->hurt_by_lara();
|
||||
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.IsJumping = savedCreature->is_jumping();
|
||||
creature->LOT.IsMonkeying = savedCreature->is_monkeying();
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
creature->JointRotation[j] = savedCreature->joint_rotation()->Get(j);
|
||||
|
||||
creature->JumpAhead = savedCreature->jump_ahead();
|
||||
creature->MaxTurn = savedCreature->maximum_turn();
|
||||
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++)
|
||||
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.CanClimbLadder = s->lara()->control()->is_climbing_ladder();
|
||||
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.y = s->lara()->extra_torso_rot()->y();
|
||||
Lara.ExtraTorsoRot.z = s->lara()->extra_torso_rot()->z();
|
||||
Lara.WaterCurrentActive = s->lara()->water_current_active();
|
||||
Lara.WaterCurrentPull.x = s->lara()->water_current_pull()->x();
|
||||
Lara.WaterCurrentPull.y = s->lara()->water_current_pull()->y();
|
||||
Lara.WaterCurrentPull.z = s->lara()->water_current_pull()->z();
|
||||
Lara.Context.WaterCurrentActive = s->lara()->water_current_active();
|
||||
Lara.Context.WaterCurrentPull.x = s->lara()->water_current_pull()->x();
|
||||
Lara.Context.WaterCurrentPull.y = s->lara()->water_current_pull()->y();
|
||||
Lara.Context.WaterCurrentPull.z = s->lara()->water_current_pull()->z();
|
||||
Lara.Flare.Life = s->lara()->flare()->life();
|
||||
Lara.Flare.ControlLeft = s->lara()->flare()->control_left();
|
||||
Lara.Flare.Frame = s->lara()->flare()->frame();
|
||||
Lara.HighestLocation = s->lara()->highest_location();
|
||||
Lara.HitDirection = s->lara()->hit_direction();
|
||||
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.BeetleLife = s->lara()->inventory()->beetle_life();
|
||||
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.Location = s->lara()->location();
|
||||
Lara.LocationPad = s->lara()->location_pad();
|
||||
Lara.NextCornerPos = ToPHD(s->lara()->next_corner_pose());
|
||||
Lara.ProjectedFloorHeight = s->lara()->projected_floor_height();
|
||||
Lara.Context.NextCornerPos = ToPHD(s->lara()->next_corner_pose());
|
||||
Lara.Context.ProjectedFloorHeight = s->lara()->projected_floor_height();
|
||||
Lara.RightArm.AnimNumber = s->lara()->right_arm()->anim_number();
|
||||
Lara.RightArm.GunFlash = s->lara()->right_arm()->gun_flash();
|
||||
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.TargetArmOrient.y = s->lara()->target_arm_angles()->Get(0);
|
||||
Lara.TargetArmOrient.x = s->lara()->target_arm_angles()->Get(1);
|
||||
Lara.TargetOrientation.y = s->lara()->target_facing_angle();
|
||||
Lara.Vehicle = s->lara()->vehicle();
|
||||
Lara.WaterSurfaceDist = s->lara()->water_surface_dist();
|
||||
Lara.Context.TargetOrientation.y = s->lara()->target_facing_angle();
|
||||
Lara.Context.Vehicle = s->lara()->vehicle();
|
||||
Lara.Context.WaterSurfaceDist = s->lara()->water_surface_dist();
|
||||
|
||||
for (int i = 0; i < s->lara()->weapons()->size(); i++)
|
||||
{
|
||||
|
@ -1988,10 +2056,10 @@ bool SaveGame::Load(int slot)
|
|||
|
||||
std::vector<SavedVar> loadedVars;
|
||||
|
||||
auto theVec = s->script_vars();
|
||||
if (theVec)
|
||||
auto unionVec = s->script_vars();
|
||||
if (unionVec)
|
||||
{
|
||||
for (auto const& var : *(theVec->members()))
|
||||
for (const auto& var : *(unionVec->members()))
|
||||
{
|
||||
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& loadedTab = loadedVars.emplace_back(IndexTable{});
|
||||
|
||||
for (auto const& p : *tab)
|
||||
{
|
||||
std::get<IndexTable>(loadedTab).push_back(std::make_pair(p->key(), p->val()));
|
||||
}
|
||||
for (const auto& pair : *tab)
|
||||
std::get<IndexTable>(loadedTab).push_back(std::make_pair(pair->key(), pair->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)
|
||||
{
|
||||
auto stored = var->u_as_vec3()->vec();
|
||||
SavedVar v;
|
||||
v.emplace<(int)SavedVarType::Vec3>(ToVector3i(stored));
|
||||
loadedVars.push_back(v);
|
||||
SavedVar var;
|
||||
var.emplace<(int)SavedVarType::Vec3>(ToVector3i(stored));
|
||||
loadedVars.push_back(var);
|
||||
}
|
||||
else if (var->u_type() == Save::VarUnion::rotation)
|
||||
{
|
||||
auto stored = var->u_as_rotation()->vec();
|
||||
SavedVar v;
|
||||
v.emplace<(int)SavedVarType::Rotation>(ToVector3(stored));
|
||||
loadedVars.push_back(v);
|
||||
SavedVar var;
|
||||
var.emplace<(int)SavedVarType::Rotation>(ToVector3(stored));
|
||||
loadedVars.push_back(var);
|
||||
}
|
||||
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()});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
g_GameScript->SetVariables(loadedVars);
|
||||
|
||||
std::vector<std::string> callbacksPreControlVec;
|
||||
auto callbacksPreControlOffsetVec = s->callbacks_pre_control();
|
||||
for (auto const& s : *callbacksPreControlOffsetVec)
|
||||
callbacksPreControlVec.push_back(s->str());
|
||||
auto populateCallbackVecs = [&s](auto callbackFunc)
|
||||
{
|
||||
auto callbacksVec = std::vector<std::string>{};
|
||||
auto callbacksOffsetVec = std::invoke(callbackFunc, s);
|
||||
|
||||
std::vector<std::string> callbacksPostControlVec;
|
||||
auto callbacksPostControlOffsetVec = s->callbacks_post_control();
|
||||
for (auto const& s : *callbacksPostControlOffsetVec)
|
||||
callbacksPostControlVec.push_back(s->str());
|
||||
for (const auto& e : *callbacksOffsetVec)
|
||||
callbacksVec.push_back(e->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;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ void ClearSpotCamSequences()
|
|||
SpotCam[i] = {};
|
||||
}
|
||||
|
||||
void InitialiseSpotCamSequences(bool startFirstSequence)
|
||||
void InitializeSpotCamSequences(bool startFirstSequence)
|
||||
{
|
||||
TrackCameraInit = false;
|
||||
|
||||
|
@ -105,12 +105,12 @@ void InitialiseSpotCamSequences(bool startFirstSequence)
|
|||
|
||||
if (startFirstSequence)
|
||||
{
|
||||
InitialiseSpotCam(0);
|
||||
InitializeSpotCam(0);
|
||||
UseSpotCam = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InitialiseSpotCam(short Sequence)
|
||||
void InitializeSpotCam(short Sequence)
|
||||
{
|
||||
if (TrackCameraInit != 0 && LastSpotCamSequence == Sequence)
|
||||
{
|
||||
|
@ -125,7 +125,7 @@ void InitialiseSpotCam(short Sequence)
|
|||
|
||||
LaraItem->MeshBits = ALL_JOINT_BITS;
|
||||
|
||||
ResetLaraFlex(LaraItem);
|
||||
ResetPlayerFlex(LaraItem);
|
||||
|
||||
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