mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 19:38:24 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
255 lines
5.2 KiB
C#
255 lines
5.2 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace Sandbox;
|
|
|
|
[Expose]
|
|
public partial class Particle : IDynamicFloatContext
|
|
{
|
|
[ActionGraphInclude]
|
|
public Vector3 Position;
|
|
|
|
[ActionGraphInclude]
|
|
public Vector3 Size;
|
|
|
|
[ActionGraphInclude]
|
|
public Vector3 Velocity;
|
|
public Color Color;
|
|
public Color OverlayColor;
|
|
public float Alpha;
|
|
public float BornTime;
|
|
public float Age;
|
|
public float Radius;
|
|
public Angles Angles;
|
|
public int Sequence;
|
|
public Vector3 SequenceTime;
|
|
public int Frame;
|
|
|
|
int RandomSeed;
|
|
internal bool hasUpdated;
|
|
|
|
[System.Obsolete]
|
|
public float Random01;
|
|
|
|
[System.Obsolete]
|
|
public float Random02;
|
|
|
|
[System.Obsolete]
|
|
public float Random03;
|
|
|
|
[System.Obsolete]
|
|
public float Random04;
|
|
|
|
[System.Obsolete]
|
|
public float Random05;
|
|
|
|
[System.Obsolete]
|
|
public float Random06;
|
|
|
|
[System.Obsolete]
|
|
public float Random07;
|
|
|
|
[ActionGraphInclude]
|
|
public Vector3 HitPos;
|
|
[ActionGraphInclude]
|
|
public Vector3 HitNormal;
|
|
|
|
public float HitTime;
|
|
public float LastHitTime;
|
|
public Vector3 StartPosition;
|
|
|
|
/// <summary>
|
|
/// A range from 0 to 1 descriving how long this particle has been alive
|
|
/// </summary>
|
|
public float LifeDelta;
|
|
|
|
/// <summary>
|
|
/// The time that this particle is scheduled to die
|
|
/// </summary>
|
|
public float DeathTime;
|
|
|
|
|
|
public float TimeScale;
|
|
|
|
/// <summary>
|
|
/// A GameObject that is following us. Might be emitting other particles or something.
|
|
/// </summary>
|
|
internal GameObject Follower;
|
|
|
|
|
|
public float LifeTimeRemaining => DeathTime - BornTime;
|
|
|
|
float IDynamicFloatContext.LifetimeDelta => LifeDelta;
|
|
int IDynamicFloatContext.RandomSeed => RandomSeed;
|
|
|
|
private Dictionary<string, object> _data;
|
|
|
|
public static Queue<Particle> Pool = new( 512 );
|
|
|
|
public static Particle Create()
|
|
{
|
|
if ( !Pool.TryDequeue( out Particle p ) )
|
|
{
|
|
p = new Particle();
|
|
}
|
|
|
|
p.RandomSeed = Random.Shared.Int( 0, 10000 );
|
|
p.BornTime = Time.Now;
|
|
p.Age = 0;
|
|
p.Angles = Angles.Zero;
|
|
p.Frame = 0;
|
|
p.Velocity = 0;
|
|
p.Color = Color.White;
|
|
p.OverlayColor = Color.White.WithAlpha( 0 );
|
|
p.Alpha = 1;
|
|
p.Sequence = 0;
|
|
p.SequenceTime = 0;
|
|
p.Size = 5;
|
|
p.HitTime = -1000;
|
|
p.LastHitTime = -1000;
|
|
p.TimeScale = 1;
|
|
p._data?.Clear();
|
|
p._controllers?.Clear();
|
|
p.hasUpdated = false;
|
|
|
|
return p;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get an arbituary data value
|
|
/// </summary>
|
|
public T Get<T>( string key )
|
|
{
|
|
if ( _data is null ) return default;
|
|
|
|
if ( !_data.TryGetValue( key, out var val ) )
|
|
return default;
|
|
|
|
return (T)val;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set an arbituary data value
|
|
/// </summary>
|
|
public void Set<T>( string key, T tvalue )
|
|
{
|
|
_data ??= new Dictionary<string, object>( 4, StringComparer.OrdinalIgnoreCase );
|
|
_data[key] = tvalue;
|
|
}
|
|
|
|
public void ApplyDamping( in float amount )
|
|
{
|
|
Velocity = Velocity.WithFriction( amount, 100.0f );
|
|
}
|
|
|
|
public bool MoveWithCollision( in float bounce, in float friction, in float bumpiness, in float push, in bool die, in float dt, float radius, in SceneTrace trace )
|
|
{
|
|
const float surfaceOffset = 0.1f;
|
|
|
|
// We previously hit something.
|
|
// Keep the surface normal out of our velocity
|
|
// Periodically check whether it's still there.
|
|
if ( HitTime > 0 )
|
|
{
|
|
// if time passed, or we moved too far, see if it's still there
|
|
bool recheck = HitTime < Time.Now - 0.1f || HitPos.Distance( Position ) > 16;
|
|
|
|
if ( recheck )
|
|
{
|
|
var checkTrace = trace.Ray( Position, Position + HitNormal * surfaceOffset * -2.0f )
|
|
.Radius( radius * Radius )
|
|
.Run();
|
|
|
|
if ( checkTrace.Hit )
|
|
{
|
|
HitPos = checkTrace.HitPosition;
|
|
HitNormal = checkTrace.Normal;
|
|
HitTime = Time.Now;
|
|
}
|
|
else
|
|
{
|
|
HitTime = 0;
|
|
HitPos = 0;
|
|
HitNormal = 0;
|
|
}
|
|
}
|
|
|
|
if ( HitTime > 0 )
|
|
{
|
|
LastHitTime = Time.Now;
|
|
// Keep removing the ground velocity
|
|
Velocity = Velocity.SubtractDirection( HitNormal );
|
|
}
|
|
|
|
}
|
|
|
|
if ( LastHitTime > Time.Now - 0.03f )
|
|
{
|
|
ApplyDamping( friction * dt * 5.0f );
|
|
}
|
|
|
|
var targetPosition = Position + Velocity * dt;
|
|
|
|
var tr = trace.Ray( Position, targetPosition )
|
|
.Radius( radius * Radius )
|
|
.Run();
|
|
if ( !tr.Hit )
|
|
{
|
|
Position = targetPosition;
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// If we want to die on collision then set its age to max
|
|
//
|
|
if ( die )
|
|
{
|
|
Age = float.MaxValue;
|
|
}
|
|
|
|
//
|
|
// If we have push, then push the physics object we hit
|
|
//
|
|
if ( push != 0 )
|
|
{
|
|
tr.Body.ApplyForceAt( tr.HitPosition, Velocity * tr.Body.Mass * push );
|
|
}
|
|
|
|
HitPos = tr.HitPosition;
|
|
HitNormal = tr.Normal;
|
|
HitTime = Time.Now;
|
|
|
|
var velocity = Velocity;
|
|
var speed = Velocity.Length;
|
|
|
|
var surfaceNormal = tr.Normal;
|
|
|
|
// make the hit normal bumpy if we have bumpiness
|
|
if ( speed > 10f && bumpiness > 0 )
|
|
{
|
|
surfaceNormal += Vector3.Random * bumpiness * 0.5f;
|
|
}
|
|
|
|
var surfaceVelocityNormal = velocity.SubtractDirection( surfaceNormal, 1 + bounce ).Normal;
|
|
|
|
targetPosition = tr.EndPosition;// + tr.Normal * surfaceOffset;
|
|
|
|
Velocity = surfaceVelocityNormal * speed;
|
|
|
|
if ( bounce > 0 && Velocity.Dot( tr.Normal ) > 5.0f )
|
|
{
|
|
HitTime = 0;
|
|
}
|
|
|
|
Position = targetPosition;
|
|
return true;
|
|
}
|
|
|
|
|
|
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
|
public float Rand( int seed = 0, [CallerLineNumber] int line = 0 )
|
|
{
|
|
int i = RandomSeed + (line * 20) + seed;
|
|
return Game.Random.FloatDeterministic( i );
|
|
}
|
|
}
|