Update Lua advanced particle emitter

This commit is contained in:
Sezz 2025-03-15 18:01:27 +11:00
parent b9c3856c09
commit 92b8ed821f
3 changed files with 284 additions and 293 deletions

View file

@ -124,16 +124,16 @@
<h2><a href="#Functions">Functions</a></h2> <h2><a href="#Functions">Functions</a></h2>
<table class="function_list"> <table class="function_list">
<tr> <tr>
<td class="name" ><a href="#EmitLightningArc">EmitLightningArc(src, dest, color, lifetime, amplitude, beamWidth, detail, smooth, endDrift)</a></td> <td class="name" ><a href="#EmitLightningArc">EmitLightningArc(origin, target, color, life, amplitude, beamWidth, detail, smooth, endDrift)</a></td>
<td class="summary">Emit a lightning arc.</td> <td class="summary">Emit a lightning arc.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#EmitParticle">EmitParticle(pos, vel, spriteID, gravity, rotVel, startColor, endColor, blendMode, startSize, endSize, life, applyDamage, applyPoison, spriteSeqID, startRot)</a></td> <td class="name" ><a href="#EmitParticle">EmitParticle(pos, vel, spriteID, gravity, rotVel, startColor, endColor, blendMode, startSize, endSize, life, damage, poison, spriteSeqID, startRot)</a></td>
<td class="summary">Emit a particle.</td> <td class="summary">Emit a particle.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#EmitAdvancedParticle">EmitAdvancedParticle(ParticleData)</a></td> <td class="name" ><a href="#EmitAdvancedParticle">EmitAdvancedParticle(ParticleData)</a></td>
<td class="summary">Emit a particle with extensive configuration options including animations.</td> <td class="summary">Emit a particle with extensive configuration options, including sprite sequence animation, lights, sounds, and damage effects.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#EmitShockwave">EmitShockwave(pos, innerRadius, outerRadius, color, lifetime, speed, angle, hurtsLara)</a></td> <td class="name" ><a href="#EmitShockwave">EmitShockwave(pos, innerRadius, outerRadius, color, lifetime, speed, angle, hurtsLara)</a></td>
@ -193,7 +193,7 @@
<dl class="function"> <dl class="function">
<dt> <dt>
<a name = "EmitLightningArc"></a> <a name = "EmitLightningArc"></a>
<strong>EmitLightningArc(src, dest, color, lifetime, amplitude, beamWidth, detail, smooth, endDrift)</strong> <strong>EmitLightningArc(origin, target, color, life, amplitude, beamWidth, detail, smooth, endDrift)</strong>
</dt> </dt>
<dd> <dd>
Emit a lightning arc. Emit a lightning arc.
@ -202,13 +202,13 @@
<h3>Parameters:</h3> <h3>Parameters:</h3>
<ul> <ul>
<li><span class="parameter">src</span> <li><span class="parameter">origin</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
</li> </li>
<li><span class="parameter">dest</span> <li><span class="parameter">target</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
@ -218,29 +218,29 @@
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span> <span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
(default Color(255, 255, 255)) (default Color(255, 255, 255))
</li> </li>
<li><span class="parameter">lifetime</span> <li><span class="parameter">life</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. (default 1.0) Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. <strong>default: 1</strong>
</li> </li>
<li><span class="parameter">amplitude</span> <li><span class="parameter">amplitude</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
"strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. (default 20) "strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. <strong>default: 20</strong>
</li> </li>
<li><span class="parameter">beamWidth</span> <li><span class="parameter">beamWidth</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
Clamped to [1, 127]. (default 2) Clamped to [1, 127]. <strong>default 2</strong>
</li> </li>
<li><span class="parameter">detail</span> <li><span class="parameter">detail</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. (default 10) Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. <strong>default: 10</strong>
</li> </li>
<li><span class="parameter">smooth</span> <li><span class="parameter">smooth</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. (default false) If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. <strong>default: false</strong>
</li> </li>
<li><span class="parameter">endDrift</span> <li><span class="parameter">endDrift</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
If true, the end of the arc will be able to gradually drift away from its destination in a random direction (default false) If true, the end of the arc will be able to gradually drift away from its destination in a random direction <strong>default: false</strong>
</li> </li>
</ul> </ul>
@ -251,7 +251,7 @@
</dd> </dd>
<dt> <dt>
<a name = "EmitParticle"></a> <a name = "EmitParticle"></a>
<strong>EmitParticle(pos, vel, spriteID, gravity, rotVel, startColor, endColor, blendMode, startSize, endSize, life, applyDamage, applyPoison, spriteSeqID, startRot)</strong> <strong>EmitParticle(pos, vel, spriteID, gravity, rotVel, startColor, endColor, blendMode, startSize, endSize, life, damage, poison, spriteSeqID, startRot)</strong>
</dt> </dt>
<dd> <dd>
Emit a particle. Emit a particle.
@ -266,59 +266,59 @@
</li> </li>
<li><span class="parameter">vel</span> <li><span class="parameter">vel</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
Velocity. Directional velocity.
</li> </li>
<li><span class="parameter">spriteID</span> <li><span class="parameter">spriteID</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
ID of the sprite in the sprite sequence object. Sprite ID in the sprite sequence slot.
</li> </li>
<li><span class="parameter">gravity</span> <li><span class="parameter">gravity</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Specifies if the particle will fall over time. Positive values ascend, negative values descend. Recommended range: [-1000 and 1000]. <strong>Default: 0</strong> Effect of gravity. Positive value ascends, negative value descends. <strong>default: 0</strong>
</li> </li>
<li><span class="parameter">rotVel</span> <li><span class="parameter">rotVel</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Rotational velocity in degrees. <strong>Default: 0</strong> Rotational velocity in degrees. <strong>default: 0</strong>
</li> </li>
<li><span class="parameter">startColor</span> <li><span class="parameter">startColor</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span> <span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color at start of life. <strong>Default: Color(255, 255, 255)</strong> Color at start of life. <strong>default: Color(255, 255, 255)</strong>
</li> </li>
<li><span class="parameter">endColor</span> <li><span class="parameter">endColor</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span> <span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color to fade toward. This will finish long before the end of the particle's life due to internal math. <strong>Default: Color(255, 255, 255)</strong> Color at end of life. This will finish long before the end of the particle's life due to internal math. <strong>default: Color(255, 255, 255)</strong>
</li> </li>
<li><span class="parameter">blendMode</span> <li><span class="parameter">blendMode</span>
<span class="types"><a class="type" href="../4 enums/Effects.BlendID.html#">BlendID</a></span> <span class="types"><a class="type" href="../4 enums/Effects.BlendID.html#">BlendID</a></span>
Render blend mode. <strong>TEN.Effects.BlendID.ALPHABLEND</strong> Render blend mode. <strong>TEN.Effects.BlendID.ALPHA_BLEND</strong>
</li> </li>
<li><span class="parameter">startSize</span> <li><span class="parameter">startSize</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Size at start of life. <strong>Default: 10</strong> Size at start of life. <strong>default: 10</strong>
</li> </li>
<li><span class="parameter">endSize</span> <li><span class="parameter">endSize</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Size at end of life. The particle will linearly shrink or grow toward this size over its lifespan. <strong>Default: 0</strong> Size at end of life. <strong>default: 0</strong>
</li> </li>
<li><span class="parameter">life</span> <li><span class="parameter">life</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Lifespan in seconds. <strong>Default: 2</strong> Lifespan in seconds. <strong>default: 2</strong>
</li> </li>
<li><span class="parameter">applyDamage</span> <li><span class="parameter">damage</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will harm the player on collision. <strong>Default: false</strong> Harm the player on collision. <strong>default: false</strong>
</li> </li>
<li><span class="parameter">applyPoison</span> <li><span class="parameter">poison</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will poison the player on collision. <strong>Default: false</strong> Poison the player on collision. <strong>default: false</strong>
</li> </li>
<li><span class="parameter">spriteSeqID</span> <li><span class="parameter">spriteSeqID</span>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#SpriteConstants">SpriteConstants</a></span> <span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#SpriteConstants">SpriteConstants</a></span>
ID of the sprite sequence object. <strong>Default: Objects.ObjID.DEFAULT_SPRITES</strong> Sprite sequence slot ID. <strong>default: Objects.ObjID.DEFAULT_SPRITES</strong>
</li> </li>
<li><span class="parameter">startRot</span> <li><span class="parameter">startRot</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Rotation at start of life. <strong>Default: random</strong> Rotation at start of life. <strong>default: random</strong>
</li> </li>
</ul> </ul>
@ -328,22 +328,21 @@
<h3>Usage:</h3> <h3>Usage:</h3>
<ul> <ul>
<pre class="example">EmitParticle( <pre class="example">EmitParticle(
pos, pos,
Vec3(<span class="global">math</span>.random(), <span class="global">math</span>.random(), <span class="global">math</span>.random()), Vec3(<span class="global">math</span>.random(), <span class="global">math</span>.random(), <span class="global">math</span>.random()),
<span class="number">22</span>, <span class="comment">-- spriteID <span class="number">22</span>, <span class="comment">-- spriteID
</span> <span class="number">0</span>, <span class="comment">-- gravity </span> <span class="number">0</span>, <span class="comment">-- gravity
</span> -<span class="number">2</span>, <span class="comment">-- rotVel </span> -<span class="number">2</span>, <span class="comment">-- rotVel
</span> Color(<span class="number">255</span>, <span class="number">0</span>, <span class="number">0</span>), <span class="comment">-- startColor </span> Color(<span class="number">255</span>, <span class="number">0</span>, <span class="number">0</span>), <span class="comment">-- startColor
</span> Color(<span class="number">0</span>, <span class="number">255</span>, <span class="number">0</span>), <span class="comment">-- endColor </span> Color(<span class="number">0</span>, <span class="number">255</span>, <span class="number">0</span>), <span class="comment">-- endColor
</span> TEN.Effects.BlendID.ADDITIVE, <span class="comment">-- blendMode </span> TEN.Effects.BlendID.ADDITIVE, <span class="comment">-- blendMode
</span> <span class="number">15</span>, <span class="comment">-- startSize </span> <span class="number">15</span>, <span class="comment">-- startSize
</span> <span class="number">50</span>, <span class="comment">-- endSize </span> <span class="number">50</span>, <span class="comment">-- endSize
</span> <span class="number">20</span>, <span class="comment">-- life </span> <span class="number">20</span>, <span class="comment">-- life
</span> <span class="keyword">false</span>, <span class="comment">-- applyDamage </span> <span class="keyword">false</span>, <span class="comment">-- damage
</span> <span class="keyword">true</span>, <span class="comment">-- applyPoison </span> <span class="keyword">true</span>, <span class="comment">-- poison
</span> Objects.ObjID.DEFAULT_SPRITES, <span class="comment">-- spriteSeqID </span> Objects.ObjID.DEFAULT_SPRITES, <span class="comment">-- spriteSeqID
</span> <span class="number">180</span> <span class="comment">-- startRot </span> <span class="number">180</span>) <span class="comment">-- startRot</span></pre>
</span> )</pre>
</ul> </ul>
</dd> </dd>
@ -352,7 +351,7 @@
<strong>EmitAdvancedParticle(ParticleData)</strong> <strong>EmitAdvancedParticle(ParticleData)</strong>
</dt> </dt>
<dd> <dd>
Emit a particle with extensive configuration options including animations. Emit a particle with extensive configuration options, including sprite sequence animation, lights, sounds, and damage effects.
@ -360,7 +359,7 @@
<ul> <ul>
<li><span class="parameter">ParticleData</span> <li><span class="parameter">ParticleData</span>
<span class="types"><a class="type" href="../1 modules/Effects.html#ParticleData">ParticleData</a></span> <span class="types"><a class="type" href="../1 modules/Effects.html#ParticleData">ParticleData</a></span>
The table holding all the particle data. Table containing particle data.
</li> </li>
</ul> </ul>
@ -369,34 +368,35 @@
<h3>Usage:</h3> <h3>Usage:</h3>
<ul> <ul>
<pre class="example"><span class="keyword">local</span> particle = { <pre class="example"><span class="keyword">local</span> particle =
position = GetMoveableByName(<span class="string">"camera_target_6"</span>) :GetPosition(), {
velocity = Vec3(<span class="number">0</span>, <span class="number">0</span>, <span class="number">10</span>), pos = GetMoveableByName(<span class="string">"camera_target_6"</span>):GetPosition(),
spriteSeqID = TEN.Objects.ObjID.CUSTOM_BAR_GRAPHIC, vel = Vec3(<span class="number">0</span>, <span class="number">0</span>, <span class="number">10</span>),
spriteID = <span class="number">0</span>, spriteSeqID = TEN.Objects.ObjID.CUSTOM_BAR_GRAPHIC,
lifetime = <span class="number">10</span>, spriteID = <span class="number">0</span>,
maxYVelocity = <span class="number">0</span>, life = <span class="number">10</span>,
gravity = <span class="number">0</span>, maxYVel = <span class="number">0</span>,
friction = <span class="number">10</span>, gravity = <span class="number">0</span>,
startRotation = <span class="number">0</span>, friction = <span class="number">10</span>,
rotationSpeed = <span class="number">0</span>, startRot = <span class="number">0</span>,
startSize = <span class="number">80</span>, rotVel = <span class="number">0</span>,
endSize = <span class="number">80</span>, startSize = <span class="number">80</span>,
startColor = TEN.Color(<span class="number">128</span>, <span class="number">128</span>, <span class="number">128</span>), endSize = <span class="number">80</span>,
endColor = TEN.Color(<span class="number">128</span>, <span class="number">128</span>, <span class="number">128</span>), startColor = TEN.Color(<span class="number">128</span>, <span class="number">128</span>, <span class="number">128</span>),
blendMode = TEN.Effects.BlendID.ADDITIVE, endColor = TEN.Color(<span class="number">128</span>, <span class="number">128</span>, <span class="number">128</span>),
wind = <span class="keyword">false</span>, blendMode = TEN.Effects.BlendID.ADDITIVE,
damage = <span class="keyword">true</span>, wind = <span class="keyword">false</span>,
poison = <span class="keyword">false</span>, damage = <span class="keyword">true</span>,
burn = <span class="keyword">false</span>, poison = <span class="keyword">false</span>,
damageHit = <span class="number">80</span>, burn = <span class="keyword">false</span>,
sound = <span class="number">197</span>, damageHit = <span class="number">80</span>,
light = <span class="keyword">true</span>, sound = <span class="number">197</span>,
lightRadius = <span class="number">6</span>, light = <span class="keyword">true</span>,
lightFlicker = <span class="number">5</span>, lightRadius = <span class="number">6</span>,
animated = <span class="keyword">true</span>, lightFlicker = <span class="number">5</span>,
frameRate = .<span class="number">25</span>, animated = <span class="keyword">true</span>,
animationType = TEN.Effects.ParticleAnimationType.LOOP, frameRate = <span class="number">0.25</span>,
animType = TEN.Effects.ParticleAnimationType.LOOP,
} }
EmitAdvancedParticle(particle)</pre> EmitAdvancedParticle(particle)</pre>
</ul> </ul>
@ -631,7 +631,7 @@ EmitAdvancedParticle(particle)</pre>
</li> </li>
<li><span class="parameter">size</span> <li><span class="parameter">size</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
(default 1.0) Fire size. <strong>default: 1</strong>
</li> </li>
</ul> </ul>
@ -790,7 +790,7 @@ EmitAdvancedParticle(particle)</pre>
</li> </li>
<li><span class="parameter">lengthFeatherMode</span> <li><span class="parameter">lengthFeatherMode</span>
<span class="types"><span class="type">Effects.StreamerFeatherMode</span></span> <span class="types"><span class="type">Effects.StreamerFeatherMode</span></span>
Length feather mode. <strong>Not implemented yet.</strong> Length feather mode. <strong>UNIMPLEMENTED, currently will always leave a fading tail</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">blendID</span> <li><span class="parameter">blendID</span>
@ -820,137 +820,137 @@ EmitAdvancedParticle(particle)</pre>
<h3>Fields:</h3> <h3>Fields:</h3>
<ul> <ul>
<li><span class="parameter">position</span> <li><span class="parameter">pos</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
World position. World position.
</li> </li>
<li><span class="parameter">velocity</span> <li><span class="parameter">vel</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
Velocity. Directional velocity in world units per second.
</li> </li>
<li><span class="parameter">spriteSeqID</span> <li><span class="parameter">spriteSeqID</span>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#SpriteConstants">SpriteConstants</a></span> <span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#SpriteConstants">SpriteConstants</a></span>
ID of the sprite sequence object. <strong>Default: Objects.ObjID.DEFAULT_SPRITES</strong> Sprite sequence slot ID. <strong>default: Objects.ObjID.DEFAULT_SPRITES</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">spriteID</span> <li><span class="parameter">spriteID</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
ID of the sprite in the sprite sequence object.<strong>Default: 0</strong> Sprite ID in the sprite sequence slot. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">lifetime</span> <li><span class="parameter">life</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Lifespan in seconds. <strong>Default: 2</strong> Lifespan in seconds. <strong>default: 2</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">maxYVelocity</span> <li><span class="parameter">maxYVel</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Specifies ithe maximum Y velocity for the particle. <strong>Default: 0</strong> Maximum vertical velocity in world units per second. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">gravity</span> <li><span class="parameter">gravity</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Specifies if the particle will fall over time. Positive values ascend, negative values descend. Recommended range: [-1000 and 1000]. <strong>Default: 0</strong> Effect of gravity in world units per second. Positive value ascend, negative value descend. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">friction</span> <li><span class="parameter">friction</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Specifies the friction with which the particle will slow down over time. <strong>Default: 0</strong> Friction affecting velocity over time in world units per second. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">startRotation</span> <li><span class="parameter">startRot</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Rotation at start of life. <strong>Default: random</strong> Rotation at start of life. <strong>default: random</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">rotationSpeed</span> <li><span class="parameter">rotVel</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Rotational velocity in degrees. <strong>Default: 0</strong> Rotational velocity in degrees per second. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">startSize</span> <li><span class="parameter">startSize</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Size at start of life. <strong>Default: 10</strong> Size at start of life. <strong>default: 10</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">endSize</span> <li><span class="parameter">endSize</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Size at end of life. The particle will linearly shrink or grow toward this size over its lifespan. <strong>Default: 0</strong> Size at end of life. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">startColor</span> <li><span class="parameter">startColor</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span> <span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color at start of life. <strong>Default: Color(255, 255, 255)</strong> Color at start of life. <strong>default: Color(255, 255, 255)</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">endColor</span> <li><span class="parameter">endColor</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span> <span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color to fade toward. This will finish long before the end of the particle's life due to internal math. <strong>Default: Color(255, 255, 255)</strong> Color at end of life. Note that this will finish long before the end of life due to internal math. <strong>default: Color(255, 255, 255)</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">blendMode</span> <li><span class="parameter">blendMode</span>
<span class="types"><a class="type" href="../4 enums/Effects.BlendID.html#">BlendID</a></span> <span class="types"><a class="type" href="../4 enums/Effects.BlendID.html#">BlendID</a></span>
Render blend mode. <strong>TEN.Effects.BlendID.ALPHA_BLEND</strong> Render blend mode. <strong>default: TEN.Effects.BlendID.ALPHA_BLEND</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">damage</span> <li><span class="parameter">damage</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will harm the player on collision. <strong>Default: false</strong> Harm the player on collision. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">poison</span> <li><span class="parameter">poison</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will poison the player on collision. <strong>Default: false</strong> Poison the player on collision. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">burn</span> <li><span class="parameter">burn</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will burn the player on collision. <strong>Default: false</strong> Burn the player on collision. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">wind</span> <li><span class="parameter">wind</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will be affected by wind in outside rooms. <strong>Default: false</strong> Affect position by wind in outside rooms. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">damageHit</span> <li><span class="parameter">damageHit</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
Specify the damage particle will harm the player on collision. <strong>Default: 2</strong> Player damage amount on collision. <strong>default: 2</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">light</span> <li><span class="parameter">light</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will be emit a light based on its color. Caution: Recommended only for a single particle. Having too many particles with lights can overflow the light system. <strong>Default: false</strong> Emit a colored light. CAUTION: Recommended only for a single particle. Too many particles with lights can overwhelm the lighting system. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">lightRadius</span> <li><span class="parameter">lightRadius</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
measured in "clicks" or 256 world units. <strong>Default: 0</strong> Light radius in 1/4 blocks. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">lightFlicker</span> <li><span class="parameter">lightFlicker</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
The interval at which light should flicker. <strong>Default: 0</strong> Interval at which the light should flicker. <strong>default: 0</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">sound</span> <li><span class="parameter">soundID</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. Looping sounds recommended. Caution: Recommended only for a single particle. Having too many particles with sounds can overflow the sound system. <strong>Default: None</strong> Sound ID to play. CAUTION: Recommended only for a single particle. Too many particles with sounds can overwhelm the sound system. <strong>default: none</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">animated</span> <li><span class="parameter">animated</span>
<span class="types"><span class="type">bool</span></span> <span class="types"><span class="type">bool</span></span>
Specify if the particle will be animated. <strong>Default: false</strong> Play animates sprite sequence. <strong>default: false</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">animationType</span> <li><span class="parameter">animType</span>
<span class="types"><a class="type" href="../4 enums/Effects.ParticleAnimationType.html#">ParticleAnimationType</a></span> <span class="types"><a class="type" href="../4 enums/Effects.ParticleAnimationType.html#">ParticleAnimationType</a></span>
Specify the the type of animation the particle will use. <strong>Default: TEN.Effects.ParticleAnimationType.LOOP</strong> Animation type of the sprite sequence. <strong>default: TEN.Effects.ParticleAnimationType.LOOP</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
<li><span class="parameter">frameRate</span> <li><span class="parameter">frameRate</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
The framerate with which the particle will be animated. <strong>Default: 1</strong> Sprite sequence animation framerate. <strong>default: 1</strong>
(<em>optional</em>) (<em>optional</em>)
</li> </li>
</ul> </ul>

View file

@ -587,8 +587,11 @@ namespace TEN::Renderer
static inline BlendMode GetBlendModeFromAlpha(BlendMode blendMode, float alpha) static inline BlendMode GetBlendModeFromAlpha(BlendMode blendMode, float alpha)
{ {
if (alpha < ALPHA_BLEND_THRESHOLD && (blendMode == BlendMode::Opaque || blendMode == BlendMode::AlphaTest || blendMode == BlendMode::FastAlphaBlend)) if (alpha < ALPHA_BLEND_THRESHOLD &&
(blendMode == BlendMode::Opaque || blendMode == BlendMode::AlphaTest || blendMode == BlendMode::FastAlphaBlend))
{
return BlendMode::AlphaBlend; return BlendMode::AlphaBlend;
}
return blendMode; return blendMode;
} }

View file

@ -48,23 +48,24 @@ using namespace TEN::Scripting::Types;
namespace TEN::Scripting::Effects namespace TEN::Scripting::Effects
{ {
/// Emit a lightning arc. /// Emit a lightning arc.
// @function EmitLightningArc // @function EmitLightningArc
// @tparam Vec3 src // @tparam Vec3 origin
// @tparam Vec3 dest // @tparam Vec3 target
// @tparam Color color (default Color(255, 255, 255)) // @tparam Color color (default Color(255, 255, 255))
// @tparam float lifetime Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. (default 1.0) // @tparam float life Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. __default: 1__
// @tparam int amplitude "strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. (default 20) // @tparam int amplitude "strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. __default: 20__
// @tparam int beamWidth Clamped to [1, 127]. (default 2) // @tparam int beamWidth Clamped to [1, 127]. __default 2__
// @tparam int detail Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. (default 10) // @tparam int detail Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. __default: 10__
// @tparam bool smooth If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. (default false) // @tparam bool smooth If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. __default: false__
// @tparam bool endDrift If true, the end of the arc will be able to gradually drift away from its destination in a random direction (default false) // @tparam bool endDrift If true, the end of the arc will be able to gradually drift away from its destination in a random direction __default: false__
static void EmitLightningArc(const Vec3& origin, const Vec3& target, TypeOrNil<ScriptColor> color, TypeOrNil<float> life, TypeOrNil<int> amplitude,
static void EmitLightningArc(Vec3 src, Vec3 dest, TypeOrNil<ScriptColor> color, TypeOrNil<float> lifetime, TypeOrNil<int> amplitude, TypeOrNil<int> beamWidth, TypeOrNil<int> segments, TypeOrNil<bool> smooth, TypeOrNil<bool> endDrift) TypeOrNil<int> beamWidth, TypeOrNil<int> segments, TypeOrNil<bool> smooth, TypeOrNil<bool> endDrift)
{ {
auto p1 = Vector3(src.x, src.y, src.z); constexpr auto LIFE_SEC_MAX = 4.233f;
auto p2 = Vector3(dest.x, dest.y, dest.z);
auto convertedOrigin = origin.ToVector3();
auto convertedTarget = target.ToVector3();
int segs = ValueOr<int>(segments, 10); int segs = ValueOr<int>(segments, 10);
@ -77,21 +78,20 @@ namespace TEN::Scripting::Effects
// Nearest number of milliseconds equating to approx 254, the max even byte value for "life". // Nearest number of milliseconds equating to approx 254, the max even byte value for "life".
// This takes into account a "hardcoded" FPS of 30 and the fact that // This takes into account a "hardcoded" FPS of 30 and the fact that
// lightning loses two "life" each frame. // lightning loses two "life" each frame.
constexpr auto kMaxLifeSeconds = 4.233f; float convertedLife = ValueOr<float>(life, 1.0f);
float life = ValueOr<float>(lifetime, 1.0f); convertedLife = std::clamp(convertedLife, 0.0f, LIFE_SEC_MAX);
life = std::clamp(life, 0.0f, kMaxLifeSeconds);
constexpr float secsPerFrame = 1.0f / (float)FPS; constexpr float secsPerFrame = 1.0f / (float)FPS;
// This will put us in the range [0, 127] // This will put us in the range [0, 127]
int lifeInFrames = (int)round(life / secsPerFrame); int lifeInFrames = (int)round(convertedLife / secsPerFrame);
// Multiply by two since a) lightning loses two "life" each frame, and b) it must be // Multiply by two since a) lightning loses two "life" each frame, and b) it must be
// an even number to avoid overshooting a value of 0 and wrapping around. // an even number to avoid overshooting a value of 0 and wrapping around.
byte byteLife = lifeInFrames * 2; byte byteLife = lifeInFrames * 2;
int amp = ValueOr<int>(amplitude, 20); int amp = ValueOr<int>(amplitude, 20);
byte byteAmplitude = std::clamp(amp, 1, 255); byte byteAmp = std::clamp(amp, 1, 255);
bool isSmooth = ValueOr<bool>(smooth, false); bool isSmooth = ValueOr<bool>(smooth, false);
bool isDrift = ValueOr<bool>(endDrift, false); bool isDrift = ValueOr<bool>(endDrift, false);
@ -103,47 +103,45 @@ namespace TEN::Scripting::Effects
if(isDrift) if(isDrift)
flags |= 2; flags |= 2;
ScriptColor col = ValueOr<ScriptColor>(color, ScriptColor( 255, 255, 255 )); auto convertedColor = ValueOr<ScriptColor>(color, ScriptColor( 255, 255, 255 ));
SpawnElectricity(p1, p2, byteAmplitude, col.GetR(), col.GetG(), col.GetB(), byteLife, flags, width, segs); SpawnElectricity(convertedOrigin, convertedTarget, byteAmp, convertedColor.GetR(), convertedColor.GetG(), convertedColor.GetB(), byteLife, flags, width, segs);
} }
/// Emit a particle. /// Emit a particle.
// @function EmitParticle // @function EmitParticle
// @tparam Vec3 pos World position. // @tparam Vec3 pos World position.
// @tparam Vec3 vel Velocity. // @tparam Vec3 vel Directional velocity.
// @tparam int spriteID ID of the sprite in the sprite sequence object. // @tparam int spriteID Sprite ID in the sprite sequence slot.
// @tparam float gravity Specifies if the particle will fall over time. Positive values ascend, negative values descend. Recommended range: [-1000 and 1000]. __Default: 0__ // @tparam float gravity Effect of gravity. Positive value ascends, negative value descends. __default: 0__
// @tparam float rotVel Rotational velocity in degrees. __Default: 0__ // @tparam float rotVel Rotational velocity in degrees. __default: 0__
// @tparam Color startColor Color at start of life. __Default: Color(255, 255, 255)__ // @tparam Color startColor Color at start of life. __default: Color(255, 255, 255)__
// @tparam Color endColor Color to fade toward. This will finish long before the end of the particle's life due to internal math. __Default: Color(255, 255, 255)__ // @tparam Color endColor Color at end of life. This will finish long before the end of the particle's life due to internal math. __default: Color(255, 255, 255)__
// @tparam Effects.BlendID blendMode Render blend mode. __TEN.Effects.BlendID.ALPHABLEND__ // @tparam Effects.BlendID blendMode Render blend mode. __TEN.Effects.BlendID.ALPHA_BLEND__
// @tparam float startSize Size at start of life. __Default: 10__ // @tparam float startSize Size at start of life. __default: 10__
// @tparam float endSize Size at end of life. The particle will linearly shrink or grow toward this size over its lifespan. __Default: 0__ // @tparam float endSize Size at end of life. __default: 0__
// @tparam float life Lifespan in seconds. __Default: 2__ // @tparam float life Lifespan in seconds. __default: 2__
// @tparam bool applyDamage Specify if the particle will harm the player on collision. __Default: false__ // @tparam bool damage Harm the player on collision. __default: false__
// @tparam bool applyPoison Specify if the particle will poison the player on collision. __Default: false__ // @tparam bool poison Poison the player on collision. __default: false__
// @tparam Objects.ObjID.SpriteConstants spriteSeqID ID of the sprite sequence object. __Default: Objects.ObjID.DEFAULT_SPRITES__ // @tparam Objects.ObjID.SpriteConstants spriteSeqID Sprite sequence slot ID. __default: Objects.ObjID.DEFAULT_SPRITES__
// @tparam float startRot Rotation at start of life. __Default: random__ // @tparam float startRot Rotation at start of life. __default: random__
// @usage // @usage
// EmitParticle( // EmitParticle(
// pos, // pos,
// Vec3(math.random(), math.random(), math.random()), // Vec3(math.random(), math.random(), math.random()),
// 22, -- spriteID // 22, -- spriteID
// 0, -- gravity // 0, -- gravity
// -2, -- rotVel // -2, -- rotVel
// Color(255, 0, 0), -- startColor // Color(255, 0, 0), -- startColor
// Color(0, 255, 0), -- endColor // Color(0, 255, 0), -- endColor
// TEN.Effects.BlendID.ADDITIVE, -- blendMode // TEN.Effects.BlendID.ADDITIVE, -- blendMode
// 15, -- startSize // 15, -- startSize
// 50, -- endSize // 50, -- endSize
// 20, -- life // 20, -- life
// false, -- applyDamage // false, -- damage
// true, -- applyPoison // true, -- poison
// Objects.ObjID.DEFAULT_SPRITES, -- spriteSeqID // Objects.ObjID.DEFAULT_SPRITES, -- spriteSeqID
// 180 -- startRot // 180) -- startRot
// )
static void EmitParticle(const Vec3& pos, const Vec3& vel, int spriteID, TypeOrNil<float> gravity, TypeOrNil<float> rotVel, static void EmitParticle(const Vec3& pos, const Vec3& vel, int spriteID, TypeOrNil<float> gravity, TypeOrNil<float> rotVel,
TypeOrNil<ScriptColor> startColor, TypeOrNil<ScriptColor> endColor, TypeOrNil<BlendMode> blendMode, TypeOrNil<ScriptColor> startColor, TypeOrNil<ScriptColor> endColor, TypeOrNil<BlendMode> blendMode,
TypeOrNil<float> startSize, TypeOrNil<float> endSize, TypeOrNil<float> life, TypeOrNil<float> startSize, TypeOrNil<float> endSize, TypeOrNil<float> life,
@ -217,83 +215,83 @@ namespace TEN::Scripting::Effects
part.flags |= SP_DAMAGE; part.flags |= SP_DAMAGE;
part.damage = 2; part.damage = 2;
} }
// TODO: Add option to turn off wind. // TODO: Add option to turn off wind.
if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WIND, part.roomNumber)) if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WIND, part.roomNumber))
part.flags |= SP_WIND; part.flags |= SP_WIND;
} }
/// Emit a particle with extensive configuration options including animations. /// Emit a particle with extensive configuration options, including sprite sequence animation, lights, sounds, and damage effects.
// @function EmitAdvancedParticle // @function EmitAdvancedParticle
// @tparam ParticleData ParticleData The table holding all the particle data. // @tparam ParticleData ParticleData Table containing particle data.
// @usage // @usage
// local particle = { // local particle =
// position = GetMoveableByName("camera_target_6") :GetPosition(), // {
// velocity = Vec3(0, 0, 10), // pos = GetMoveableByName("camera_target_6"):GetPosition(),
// spriteSeqID = TEN.Objects.ObjID.CUSTOM_BAR_GRAPHIC, // vel = Vec3(0, 0, 10),
// spriteID = 0, // spriteSeqID = TEN.Objects.ObjID.CUSTOM_BAR_GRAPHIC,
// lifetime = 10, // spriteID = 0,
// maxYVelocity = 0, // life = 10,
// gravity = 0, // maxYVel = 0,
// friction = 10, // gravity = 0,
// startRotation = 0, // friction = 10,
// rotationSpeed = 0, // startRot = 0,
// startSize = 80, // rotVel = 0,
// endSize = 80, // startSize = 80,
// startColor = TEN.Color(128, 128, 128), // endSize = 80,
// endColor = TEN.Color(128, 128, 128), // startColor = TEN.Color(128, 128, 128),
// blendMode = TEN.Effects.BlendID.ADDITIVE, // endColor = TEN.Color(128, 128, 128),
// wind = false, // blendMode = TEN.Effects.BlendID.ADDITIVE,
// damage = true, // wind = false,
// poison = false, // damage = true,
// burn = false, // poison = false,
// damageHit = 80, // burn = false,
// sound = 197, // damageHit = 80,
// light = true, // sound = 197,
// lightRadius = 6, // light = true,
// lightFlicker = 5, // lightRadius = 6,
// animated = true, // lightFlicker = 5,
// frameRate = .25, // animated = true,
// animationType = TEN.Effects.ParticleAnimationType.LOOP, // frameRate = 0.25,
// animType = TEN.Effects.ParticleAnimationType.LOOP,
// } // }
// EmitAdvancedParticle(particle) // EmitAdvancedParticle(particle)
/// Structure for EmitAdvancedParticle table. /// Structure for EmitAdvancedParticle table.
// @table ParticleData // @table ParticleData
// @tfield Vec3 position World position. // @tfield Vec3 pos World position.
// @tfield Vec3 velocity Velocity. // @tfield Vec3 vel Directional velocity in world units per second.
// @tfield[opt] Objects.ObjID.SpriteConstants spriteSeqID ID of the sprite sequence object. __Default: Objects.ObjID.DEFAULT_SPRITES__ // @tfield[opt] Objects.ObjID.SpriteConstants spriteSeqID Sprite sequence slot ID. __default: Objects.ObjID.DEFAULT_SPRITES__
// @tfield[opt] int spriteID ID of the sprite in the sprite sequence object.__Default: 0__ // @tfield[opt] int spriteID Sprite ID in the sprite sequence slot. __default: 0__
// @tfield[opt] float lifetime Lifespan in seconds. __Default: 2__ // @tfield[opt] float life Lifespan in seconds. __default: 2__
// @tfield[opt] float maxYVelocity Specifies ithe maximum Y velocity for the particle. __Default: 0__ // @tfield[opt] float maxYVel Maximum vertical velocity in world units per second. __default: 0__
// @tfield[opt] float gravity Specifies if the particle will fall over time. Positive values ascend, negative values descend. Recommended range: [-1000 and 1000]. __Default: 0__ // @tfield[opt] float gravity Effect of gravity in world units per second. Positive value ascend, negative value descend. __default: 0__
// @tfield[opt] float friction Specifies the friction with which the particle will slow down over time. __Default: 0__ // @tfield[opt] float friction Friction affecting velocity over time in world units per second. __default: 0__
// @tfield[opt] float startRotation Rotation at start of life. __Default: random__ // @tfield[opt] float startRot Rotation at start of life. __default: random__
// @tfield[opt] float rotationSpeed Rotational velocity in degrees. __Default: 0__ // @tfield[opt] float rotVel Rotational velocity in degrees per second. __default: 0__
// @tfield[opt] float startSize Size at start of life. __Default: 10__ // @tfield[opt] float startSize Size at start of life. __default: 10__
// @tfield[opt] float endSize Size at end of life. The particle will linearly shrink or grow toward this size over its lifespan. __Default: 0__ // @tfield[opt] float endSize Size at end of life. __default: 0__
// @tfield[opt] Color startColor Color at start of life. __Default: Color(255, 255, 255)__ // @tfield[opt] Color startColor Color at start of life. __default: Color(255, 255, 255)__
// @tfield[opt] Color endColor Color to fade toward. This will finish long before the end of the particle's life due to internal math. __Default: Color(255, 255, 255)__ // @tfield[opt] Color endColor Color at end of life. Note that this will finish long before the end of life due to internal math. __default: Color(255, 255, 255)__
// @tfield[opt] Effects.BlendID blendMode Render blend mode. __TEN.Effects.BlendID.ALPHA_BLEND__ // @tfield[opt] Effects.BlendID blendMode Render blend mode. __default: TEN.Effects.BlendID.ALPHA_BLEND__
// @tfield[opt] bool damage Specify if the particle will harm the player on collision. __Default: false__ // @tfield[opt] bool damage Harm the player on collision. __default: false__
// @tfield[opt] bool poison Specify if the particle will poison the player on collision. __Default: false__ // @tfield[opt] bool poison Poison the player on collision. __default: false__
// @tfield[opt] bool burn Specify if the particle will burn the player on collision. __Default: false__ // @tfield[opt] bool burn Burn the player on collision. __default: false__
// @tfield[opt] bool wind Specify if the particle will be affected by wind in outside rooms. __Default: false__ // @tfield[opt] bool wind Affect position by wind in outside rooms. __default: false__
// @tfield[opt] int damageHit Specify the damage particle will harm the player on collision. __Default: 2__ // @tfield[opt] int damageHit Player damage amount on collision. __default: 2__
// @tfield[opt] bool light Specify if the particle will be emit a light based on its color. Caution: Recommended only for a single particle. Having too many particles with lights can overflow the light system. __Default: false__ // @tfield[opt] bool light Emit a colored light. CAUTION: Recommended only for a single particle. Too many particles with lights can overwhelm the lighting system. __default: false__
// @tfield[opt] int lightRadius measured in "clicks" or 256 world units. __Default: 0__ // @tfield[opt] int lightRadius Light radius in 1/4 blocks. __default: 0__
// @tfield[opt] int lightFlicker The interval at which light should flicker. __Default: 0__ // @tfield[opt] int lightFlicker Interval at which the light should flicker. __default: 0__
// @tfield[opt] int sound ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. Looping sounds recommended. Caution: Recommended only for a single particle. Having too many particles with sounds can overflow the sound system. __Default: None__ // @tfield[opt] int soundID Sound ID to play. CAUTION: Recommended only for a single particle. Too many particles with sounds can overwhelm the sound system. __default: none__
// @tfield[opt] bool animated Specify if the particle will be animated. __Default: false__ // @tfield[opt] bool animated Play animates sprite sequence. __default: false__
// @tfield[opt] Effects.ParticleAnimationType animationType Specify the the type of animation the particle will use. __Default: TEN.Effects.ParticleAnimationType.LOOP__ // @tfield[opt] Effects.ParticleAnimationType animType Animation type of the sprite sequence. __default: TEN.Effects.ParticleAnimationType.LOOP__
// @tfield[opt] float frameRate The framerate with which the particle will be animated. __Default: 1__ // @tfield[opt] float frameRate Sprite sequence animation framerate. __default: 1__
static void EmitAdvancedParticle(const sol::table& table)
static void EmitAdvancedParticle(sol::table ParticleData)
{ {
constexpr auto DEFAULT_START_SIZE = 10.0f; constexpr auto DEFAULT_START_SIZE = 10.0f;
constexpr auto DEFAULT_LIFE = 2.0f; constexpr auto DEFAULT_LIFE = 2.0f;
constexpr auto SECS_PER_FRAME = 1.0f / (float)FPS;
auto convertedSpriteSeqID = ParticleData.get_or("spriteSeqID", ID_DEFAULT_SPRITES); auto convertedSpriteSeqID = table.get_or("spriteSeqID", ID_DEFAULT_SPRITES);
if (!CheckIfSlotExists(convertedSpriteSeqID, "EmitParticle() script function.")) if (!CheckIfSlotExists(convertedSpriteSeqID, "EmitParticle() script function."))
return; return;
@ -301,106 +299,105 @@ namespace TEN::Scripting::Effects
part.on = true; part.on = true;
part.SpriteSeqID = convertedSpriteSeqID; part.SpriteSeqID = convertedSpriteSeqID;
part.SpriteID = ParticleData.get_or("spriteID", 0); part.SpriteID = table.get_or("spriteID", 0);
auto bMode = ParticleData.get_or("blendMode", BlendMode::AlphaBlend); auto bMode = table.get_or("blendMode", BlendMode::AlphaBlend);
part.blendMode = bMode; part.blendMode = bMode;
Vec3 pos = ParticleData["position"]; auto pos = (Vec3)table["pos"];
part.x = pos.x; part.x = pos.x;
part.y = pos.y; part.y = pos.y;
part.z = pos.z; part.z = pos.z;
part.roomNumber = FindRoomNumber(Vector3i(pos.x, pos.y, pos.z)); part.roomNumber = FindRoomNumber(pos.ToVector3i());
Vec3 vel = ParticleData["velocity"]; auto vel = ((Vec3)table["vel"]) / (float)FPS;
part.xVel = short(vel.x * 32); part.xVel = short(vel.x * 32);
part.yVel = short(vel.y * 32); part.yVel = short(vel.y * 32);
part.zVel = short(vel.z * 32); part.zVel = short(vel.z * 32);
float rotAdd = ParticleData.get_or("rotationSpeed", 0.0f); float startRot = table.get_or("startRot", TO_DEGREES(Random::GenerateAngle()));
float rotAng = ParticleData.get_or("startRotation", TO_DEGREES(Random::GenerateAngle())); float rotVel = table.get_or("rotVel", 0.0f) / (float)FPS;
part.rotAng = ANGLE(rotAng) >> 4; part.rotAng = ANGLE(startRot) >> 4;
part.rotAdd = ANGLE(rotAdd) >> 4; part.rotAdd = ANGLE(rotVel) >> 4;
part.sSize = part.sSize =
part.size = ParticleData.get_or("startSize", DEFAULT_START_SIZE); part.size = table.get_or("startSize", DEFAULT_START_SIZE);
part.dSize = ParticleData.get_or("endSize", 0.0f); part.dSize = table.get_or("endSize", 0.0f);
part.scalar = 2; part.scalar = 2;
part.gravity = (short)std::clamp((float) ParticleData.get_or("gravity", 0.0f), (float)SHRT_MIN, (float)SHRT_MAX); part.gravity = (short)(std::clamp<float>(table.get_or("gravity", 0.0f), SHRT_MIN, SHRT_MAX) / (float)FPS);
part.friction = ParticleData.get_or("friction", 0); part.friction = table.get_or("friction", 0.0f) / (float)FPS;
part.maxYvel = ParticleData.get_or("maxYVelocity", 0); part.maxYvel = table.get_or("maxYVel", 0.0f) / (float)FPS;
auto convertedStartColor = ParticleData.get_or("startColor", ScriptColor(255, 255, 255)); auto convertedStartColor = table.get_or("startColor", ScriptColor(255, 255, 255));
part.sR = convertedStartColor.GetR(); part.sR = convertedStartColor.GetR();
part.sG = convertedStartColor.GetG(); part.sG = convertedStartColor.GetG();
part.sB = convertedStartColor.GetB(); part.sB = convertedStartColor.GetB();
auto convertedEndColor = ParticleData.get_or("endColor", ScriptColor(255, 255, 255)); auto convertedEndColor = table.get_or("endColor", ScriptColor(255, 255, 255));
part.dR = convertedEndColor.GetR(); part.dR = convertedEndColor.GetR();
part.dG = convertedEndColor.GetG(); part.dG = convertedEndColor.GetG();
part.dB = convertedEndColor.GetB(); part.dB = convertedEndColor.GetB();
float convertedLife = std::max(0.1f, (float) ParticleData.get_or("lifetime", DEFAULT_LIFE)); float convertedLife = std::max(0.1f, (float)table.get_or("life", DEFAULT_LIFE));
part.life = part.life =
part.sLife = (int)round(convertedLife / SECS_PER_FRAME); part.sLife = (int)round(convertedLife / (1.0f / (float)FPS));
part.colFadeSpeed = part.life / 2; part.colFadeSpeed = part.life / 2;
part.fadeToBlack = part.life / 3; part.fadeToBlack = part.life / 3;
part.flags = SP_SCALE | SP_ROTATE | SP_DEF | SP_EXPDEF; part.flags = SP_SCALE | SP_ROTATE | SP_DEF | SP_EXPDEF;
part.damage = ParticleData.get_or("damageHit", 2); part.damage = table.get_or("damageHit", 2);
bool convertedApplyPoison = ParticleData.get_or("poison", false); bool convertedApplyPoison = table.get_or("poison", false);
if (convertedApplyPoison) if (convertedApplyPoison)
part.flags |= SP_POISON; part.flags |= SP_POISON;
bool convertedApplyDamage = ParticleData.get_or("damage", false); bool convertedApplyDamage = table.get_or("damage", false);
if (convertedApplyDamage) if (convertedApplyDamage)
part.flags |= SP_DAMAGE; part.flags |= SP_DAMAGE;
bool convertedApplyBurn = ParticleData.get_or("burn", false); bool convertedApplyBurn = table.get_or("burn", false);
if (convertedApplyBurn) if (convertedApplyBurn)
part.flags |= SP_FIRE; part.flags |= SP_FIRE;
int convertedApplySound = ParticleData.get_or("sound", -1); int convertedSoundID = table.get_or("sound", NO_VALUE);
if (convertedApplySound > 0) if (convertedSoundID != NO_VALUE)
{ {
part.flags |= SP_SOUND; part.flags |= SP_SOUND;
part.sound = convertedApplySound; part.sound = convertedSoundID;
} }
bool convertedApplyLight = ParticleData.get_or("light", false); bool convertedApplyLight = table.get_or("light", false);
if (convertedApplyLight) if (convertedApplyLight)
{ {
part.flags |= SP_LIGHT; part.flags |= SP_LIGHT;
int lightRadius = ParticleData.get_or("lightRadius", 0); int lightRadius = table.get_or("lightRadius", 0);
part.lightRadius = lightRadius * BLOCK(0.25f); part.lightRadius = lightRadius * BLOCK(0.25f);
int flicker = ParticleData.get_or("lightFlicker", 0); int flicker = table.get_or("lightFlicker", 0);
if (flicker > 0) if (flicker > 0)
{ {
part.lightFlicker = ParticleData.get_or("lightFlicker", 0); part.lightFlicker = table.get_or("lightFlicker", 0);
part.lightFlickerS = ParticleData.get_or("lightFlicker", 0); part.lightFlickerS = table.get_or("lightFlicker", 0);
} }
} }
bool animatedSpr = ParticleData.get_or("animated", false); bool animatedSpr = table.get_or("animated", false);
if (animatedSpr) if (animatedSpr)
{ {
ParticleAnimType applyAnim = ParticleData.get_or("animationType", ParticleAnimType::Loop); auto applyAnim = (ParticleAnimType)table.get_or("animType", ParticleAnimType::Loop);
float applyFramerate = ParticleData.get_or("frameRate", 1.0f); float applyFramerate = table.get_or("frameRate", 1.0f);
part.flags |= SP_ANIMATED; part.flags |= SP_ANIMATED;
part.framerate = applyFramerate; part.framerate = applyFramerate;
part.animationType = ParticleAnimType(std::clamp(int(applyAnim), int(ParticleAnimType::None), int(ParticleAnimType::LifetimeSpread))); part.animationType = ParticleAnimType(std::clamp(int(applyAnim), int(ParticleAnimType::None), int(ParticleAnimType::LifetimeSpread)));
} }
bool convertedApplyWind = ParticleData.get_or("wind", false); bool convertedApplyWind = table.get_or("wind", false);
if (convertedApplyWind) if (convertedApplyWind)
{ {
if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WIND, part.roomNumber)) if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WIND, part.roomNumber))
part.flags |= SP_WIND; part.flags |= SP_WIND;
} }
} }
/// Emit a shockwave, similar to that seen when a harpy projectile hits something. /// Emit a shockwave, similar to that seen when a harpy projectile hits something.
@ -413,7 +410,6 @@ namespace TEN::Scripting::Effects
// @tparam int speed (default 50) Initial speed of the shockwave's expansion (the shockwave will always slow as it goes) // @tparam int speed (default 50) Initial speed of the shockwave's expansion (the shockwave will always slow as it goes)
// @tparam int angle (default 0) Angle about the X axis - a value of 90 will cause the shockwave to be entirely vertical // @tparam int angle (default 0) Angle about the X axis - a value of 90 will cause the shockwave to be entirely vertical
// @tparam bool hurtsLara (default false) If true, the shockwave will hurt Lara, with the damage being relative to the shockwave's current speed // @tparam bool hurtsLara (default false) If true, the shockwave will hurt Lara, with the damage being relative to the shockwave's current speed
static void EmitShockwave(Vec3 pos, TypeOrNil<int> innerRadius, TypeOrNil<int> outerRadius, TypeOrNil<ScriptColor> col, static void EmitShockwave(Vec3 pos, TypeOrNil<int> innerRadius, TypeOrNil<int> outerRadius, TypeOrNil<ScriptColor> col,
TypeOrNil<float> lifetime, TypeOrNil<int> speed, TypeOrNil<int> angle, TypeOrNil<bool> hurtPlayer) TypeOrNil<float> lifetime, TypeOrNil<int> speed, TypeOrNil<int> angle, TypeOrNil<bool> hurtPlayer)
{ {
@ -452,7 +448,6 @@ namespace TEN::Scripting::Effects
// @tparam[opt] int radius measured in "clicks" or 256 world units (default 20) // @tparam[opt] int radius measured in "clicks" or 256 world units (default 20)
// @tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false) // @tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false)
// @tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights) // @tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
static void EmitLight(Vec3 pos, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name) static void EmitLight(Vec3 pos, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name)
{ {
auto color = ValueOr<ScriptColor>(col, ScriptColor(255, 255, 255)); auto color = ValueOr<ScriptColor>(col, ScriptColor(255, 255, 255));
@ -471,7 +466,6 @@ namespace TEN::Scripting::Effects
// @tparam[opt] int distance distance, at which light cone fades out, measured in "clicks" (default 20) // @tparam[opt] int distance distance, at which light cone fades out, measured in "clicks" (default 20)
// @tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false) // @tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false)
// @tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights) // @tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
static void EmitSpotLight(Vec3 pos, Vec3 dir, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<int> falloff, TypeOrNil<int> distance, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name) static void EmitSpotLight(Vec3 pos, Vec3 dir, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<int> falloff, TypeOrNil<int> distance, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name)
{ {
auto color = ValueOr<ScriptColor>(col, ScriptColor(255, 255, 255)); auto color = ValueOr<ScriptColor>(col, ScriptColor(255, 255, 255));
@ -485,7 +479,6 @@ namespace TEN::Scripting::Effects
// @function EmitBlood // @function EmitBlood
// @tparam Vec3 pos // @tparam Vec3 pos
// @tparam int count Sprite count. __default: 1__ // @tparam int count Sprite count. __default: 1__
static void EmitBlood(const Vec3& pos, TypeOrNil<int> count) static void EmitBlood(const Vec3& pos, TypeOrNil<int> count)
{ {
TriggerBlood(pos.x, pos.y, pos.z, -1, ValueOr<int>(count, 1)); TriggerBlood(pos.x, pos.y, pos.z, -1, ValueOr<int>(count, 1));
@ -496,7 +489,6 @@ namespace TEN::Scripting::Effects
// @tparam Vec3 pos World position where the effect will be spawned. Must be in a water room. // @tparam Vec3 pos World position where the effect will be spawned. Must be in a water room.
// @tparam[opt] float size Sprite size. __Default: 32__ // @tparam[opt] float size Sprite size. __Default: 32__
// @tparam[opt] float amp Oscillation amplitude. __Default: 32__ // @tparam[opt] float amp Oscillation amplitude. __Default: 32__
static void EmitAirBubble(const Vec3& pos, TypeOrNil<float> size, TypeOrNil<float> amp) static void EmitAirBubble(const Vec3& pos, TypeOrNil<float> size, TypeOrNil<float> amp)
{ {
constexpr auto DEFAULT_SIZE = 128.0f; constexpr auto DEFAULT_SIZE = 128.0f;
@ -511,11 +503,10 @@ namespace TEN::Scripting::Effects
/// Emit fire for one frame. Will not hurt player. Call this each frame if you want a continuous fire. /// Emit fire for one frame. Will not hurt player. Call this each frame if you want a continuous fire.
// @function EmitFire // @function EmitFire
// @tparam Vec3 pos // @tparam Vec3 pos
// @tparam float size (default 1.0) // @tparam float size Fire size. __default: 1__
static void EmitFire(const Vec3& pos, TypeOrNil<float> size) static void EmitFire(const Vec3& pos, TypeOrNil<float> size)
{ {
AddFire(pos.x, pos.y, pos.z, FindRoomNumber(Vector3i(pos.x, pos.y, pos.z)), ValueOr<float>(size, 1)); AddFire(pos.x, pos.y, pos.z, FindRoomNumber(pos.ToVector3i()), ValueOr<float>(size, 1));
} }
/// Make an explosion. Does not hurt Lara /// Make an explosion. Does not hurt Lara
@ -523,7 +514,6 @@ namespace TEN::Scripting::Effects
// @tparam Vec3 pos // @tparam Vec3 pos
// @tparam float size (default 512.0) this will not be the size of the sprites, but rather the distance between the origin and any additional sprites // @tparam float size (default 512.0) this will not be the size of the sprites, but rather the distance between the origin and any additional sprites
// @tparam bool shockwave (default false) if true, create a very faint white shockwave which will not hurt Lara // @tparam bool shockwave (default false) if true, create a very faint white shockwave which will not hurt Lara
static void MakeExplosion(Vec3 pos, TypeOrNil<float> size, TypeOrNil<bool> shockwave) static void MakeExplosion(Vec3 pos, TypeOrNil<float> size, TypeOrNil<bool> shockwave)
{ {
TriggerExplosion(Vector3(pos.x, pos.y, pos.z), ValueOr<float>(size, 512.0f), true, false, ValueOr<bool>(shockwave, false), FindRoomNumber(Vector3i(pos.x, pos.y, pos.z))); TriggerExplosion(Vector3(pos.x, pos.y, pos.z), ValueOr<float>(size, 512.0f), true, false, ValueOr<bool>(shockwave, false), FindRoomNumber(Vector3i(pos.x, pos.y, pos.z)));
@ -532,7 +522,6 @@ namespace TEN::Scripting::Effects
/// Make an earthquake /// Make an earthquake
// @function MakeEarthquake // @function MakeEarthquake
// @tparam int strength (default 100) How strong should the earthquake be? Increasing this value also increases the lifespan of the earthquake. // @tparam int strength (default 100) How strong should the earthquake be? Increasing this value also increases the lifespan of the earthquake.
static void Earthquake(TypeOrNil<int> strength) static void Earthquake(TypeOrNil<int> strength)
{ {
int str = ValueOr<int>(strength, 100); int str = ValueOr<int>(strength, 100);
@ -543,32 +532,31 @@ namespace TEN::Scripting::Effects
// This represents the 3D displacement applied by the engine on things like particles affected by wind. // This represents the 3D displacement applied by the engine on things like particles affected by wind.
// @function GetWind() // @function GetWind()
// @treturn Vec3 Wind vector. // @treturn Vec3 Wind vector.
static Vec3 GetWind() static Vec3 GetWind()
{ {
return Vec3(Weather.Wind()); return Vec3(Weather.Wind());
} }
/// Emit an extending streamer effect. /// Emit an extending streamer effect.
// @function EmitStreamer // @function EmitStreamer
// @tparam Moveable mov Moveable object with which to associate the effect. // @tparam Moveable mov Moveable object with which to associate the effect.
// @tparam int[opt] tag Numeric tag with which to associate the effect on the moveable. __Default: 0__ // @tparam int[opt] tag Numeric tag with which to associate the effect on the moveable. __Default: 0__
// @tparam Vec3 pos World position. // @tparam Vec3 pos World position.
// @tparam Vec3 dir Direction vector of movement velocity. // @tparam Vec3 dir Direction vector of movement velocity.
// @tparam[opt] float rot Start rotation in degrees. __Default: 0__ // @tparam[opt] float rot Start rotation in degrees. __Default: 0__
// @tparam[opt] Color startColor Color at the start of life. __Default: Color(255, 255, 255, 255))__ // @tparam[opt] Color startColor Color at the start of life. __Default: Color(255, 255, 255, 255))__
// @tparam[opt] Color endColor Color at the end of life. __Default: Color(0, 0, 0, 0))__ // @tparam[opt] Color endColor Color at the end of life. __Default: Color(0, 0, 0, 0))__
// @tparam[opt] float width Width in world units. __Default: 0__ // @tparam[opt] float width Width in world units. __Default: 0__
// @tparam[opt] float life Lifetime in seconds. __Default: 1__ // @tparam[opt] float life Lifetime in seconds. __Default: 1__
// @tparam[opt] float vel Movement velocity in world units per second. __Default: 0__ // @tparam[opt] float vel Movement velocity in world units per second. __Default: 0__
// @tparam[opt] float expRate Width expansion rate in world units per second. __Default: 0__ // @tparam[opt] float expRate Width expansion rate in world units per second. __Default: 0__
// @tparam[opt] float rotRate Rotation rate in degrees per second. __Default: 0__ // @tparam[opt] float rotRate Rotation rate in degrees per second. __Default: 0__
// @tparam[opt] Effects.StreamerFeatherMode edgeFeatherMode Edge feather mode. __Default: Effects.FeatherID.NONE__ // @tparam[opt] Effects.StreamerFeatherMode edgeFeatherMode Edge feather mode. __Default: Effects.FeatherID.NONE__
// @tparam[opt] Effects.StreamerFeatherMode lengthFeatherMode Length feather mode. __Not implemented yet.__ // @tparam[opt] Effects.StreamerFeatherMode lengthFeatherMode Length feather mode. __UNIMPLEMENTED, currently will always leave a fading tail__
// @tparam[opt] Effects.BlendID blendID Renderer blend ID. __Default: Effects.BlendID.ALPHA_BLEND__ // @tparam[opt] Effects.BlendID blendID Renderer blend ID. __Default: Effects.BlendID.ALPHA_BLEND__
static void EmitStreamer(const Moveable& mov, TypeOrNil<int> tag, const Vec3& pos, const Vec3& dir, TypeOrNil<float> rot, TypeOrNil<ScriptColor> startColor, TypeOrNil<ScriptColor> endColor, static void EmitStreamer(const Moveable& mov, TypeOrNil<int> tag, const Vec3& pos, const Vec3& dir, TypeOrNil<float> rot, TypeOrNil<ScriptColor> startColor, TypeOrNil<ScriptColor> endColor,
TypeOrNil<float> width, TypeOrNil<float> life, TypeOrNil<float> vel, TypeOrNil<float> expRate, TypeOrNil<float> rotRate, TypeOrNil<float> width, TypeOrNil<float> life, TypeOrNil<float> vel, TypeOrNil<float> expRate, TypeOrNil<float> rotRate,
TypeOrNil<StreamerFeatherMode> edgeFeatherMode, TypeOrNil<StreamerFeatherMode> lengthFeatherMode, TypeOrNil<BlendMode> blendID) TypeOrNil<StreamerFeatherMode> edgeFeatherMode, TypeOrNil<StreamerFeatherMode> lengthFeatherMode, TypeOrNil<BlendMode> blendID)
{ {
int movID = mov.GetIndex(); int movID = mov.GetIndex();
int convertedTag = ValueOr<int>(tag, 0); int convertedTag = ValueOr<int>(tag, 0);
@ -585,13 +573,13 @@ namespace TEN::Scripting::Effects
auto convertedRotRate = ANGLE(ValueOr<float>(rotRate, 0.0f) / (float)FPS); auto convertedRotRate = ANGLE(ValueOr<float>(rotRate, 0.0f) / (float)FPS);
auto convertedEdgeFeatherID = ValueOr<StreamerFeatherMode>(edgeFeatherMode, StreamerFeatherMode::None); auto convertedEdgeFeatherID = ValueOr<StreamerFeatherMode>(edgeFeatherMode, StreamerFeatherMode::None);
auto convertedLengthFeatherID = ValueOr<StreamerFeatherMode>(lengthFeatherMode, StreamerFeatherMode::None); auto convertedLengthFeatherID = ValueOr<StreamerFeatherMode>(lengthFeatherMode, StreamerFeatherMode::Left);
auto convertedBlendID = ValueOr<BlendMode>(blendID, BlendMode::AlphaBlend); auto convertedBlendID = ValueOr<BlendMode>(blendID, BlendMode::AlphaBlend);
StreamerEffect.Spawn( StreamerEffect.Spawn(
movID, convertedTag, convertedPos, convertedDir, convertedRot, convertedStartColor, convertedEndColor, movID, convertedTag, convertedPos, convertedDir, convertedRot, convertedStartColor, convertedEndColor,
convertedWidth, convertedLife, convertedVel, convertedExpRate, convertedRotRate, convertedWidth, convertedLife, convertedVel, convertedExpRate, convertedRotRate,
convertedEdgeFeatherID, convertedBlendID); convertedEdgeFeatherID, /*convertedLengthFeatherID, */convertedBlendID);
} }
void Register(sol::state* state, sol::table& parent) void Register(sol::state* state, sol::table& parent)