@@ -15,9 +15,9 @@ public sealed class ClientDreamParticlesSystem : SharedDreamParticlesSystem {
1515 [ Dependency ] private readonly ClientAppearanceSystem _appearanceSystem = default ! ;
1616 [ Dependency ] private readonly IDreamInterfaceManager _dreamInterfaceManager = default ! ;
1717 [ Dependency ] private readonly IClyde _clyde = default ! ;
18+ [ Dependency ] private readonly IRobustRandom _random = default ! ;
1819
1920 private RenderTargetPool _renderTargetPool = default ! ;
20- private readonly Random _random = new ( ) ;
2121
2222 //used for icon GetTexture(), never needs anything but default settings
2323 private readonly RendererMetaData _defaultRenderMetaData = new ( ) ;
@@ -56,25 +56,31 @@ private ParticleSystemArgs GetParticleSystemArgs(DreamParticlesComponent compone
5656 textureFunc = ( ) => _random . Pick ( icons ) . GetTexture ( null ! , null ! , _defaultRenderMetaData , null , null ) ;
5757 }
5858
59- var result = new ParticleSystemArgs ( textureFunc , new Vector2i ( component . Width , component . Height ) , ( uint ) component . Count , component . Spawning ) {
60- Lifespan = GetGeneratorFloat ( component . LifespanLow , component . LifespanHigh , component . LifespanDist ) ,
61- Fadein = GetGeneratorFloat ( component . FadeInLow , component . FadeInHigh , component . FadeInDist ) ,
62- Fadeout = GetGeneratorFloat ( component . FadeOutLow , component . FadeOutHigh , component . FadeOutDist ) ,
59+ var perTick = ( 1f / 10f ) ; // "Tick" refers to a BYOND standard tick of 0.1s. --DM Reference
60+ var result = new ParticleSystemArgs ( textureFunc , new Vector2i ( component . Width , component . Height ) , ( uint ) component . Count , component . Spawning / perTick ) {
61+ Lifespan = ( ) => ( component . Lifespan ? . Generate ( _random ) ?? 1f ) * perTick ,
62+ Fadein = ( ) => ( component . FadeIn ? . Generate ( _random ) ?? 0f ) * perTick ,
63+ Fadeout = ( ) => ( component . FadeOut ? . Generate ( _random ) ?? 0f ) * perTick ,
6364 Color = component . Gradient . Length > 0
6465 ? lifetime => {
6566 var colorIndex = ( int ) ( lifetime * component . Gradient . Length ) ;
6667 colorIndex = Math . Clamp ( colorIndex , 0 , component . Gradient . Length - 1 ) ;
6768 return component . Gradient [ colorIndex ] ;
6869 }
6970 : _ => Color . White ,
70- Acceleration = ( _ , velocity ) => GetGeneratorVector3 ( component . AccelerationLow , component . AccelerationHigh , component . AccelerationType , component . AccelerationDist ) ( ) + GetGeneratorVector3 ( component . DriftLow , component . DriftHigh , component . DriftType , component . DriftDist ) ( ) - velocity * GetGeneratorVector3 ( component . FrictionLow , component . FrictionHigh , component . FrictionType , component . FrictionDist ) ( ) ,
71- SpawnPosition = GetGeneratorVector3 ( component . SpawnPositionLow , component . SpawnPositionHigh , component . SpawnPositionType , component . SpawnPositionDist ) ,
72- SpawnVelocity = GetGeneratorVector3 ( component . SpawnVelocityLow , component . SpawnVelocityHigh , component . SpawnVelocityType , component . SpawnVelocityDist ) ,
73- Transform = _ => {
74- var scale = GetGeneratorVector2 ( component . ScaleLow , component . ScaleHigh , component . ScaleType , component . ScaleDist ) ( ) ;
75- var rotation = GetGeneratorFloat ( component . RotationLow , component . RotationHigh , component . RotationDist ) ( ) ;
76- var growth = GetGeneratorVector2 ( component . GrowthLow , component . GrowthHigh , component . GrowthType , component . GrowthDist ) ( ) ;
77- var spin = GetGeneratorFloat ( component . SpinLow , component . SpinHigh , component . SpinDist ) ( ) ;
71+ Acceleration = ( _ , velocity ) => { // TODO: Acceleration needs to only update every tick
72+ var drift = ( component . Drift ? . GenerateVector3 ( _random ) ?? Vector3 . Zero ) ;
73+ var friction = ( component . Friction ? . GenerateVector3 ( _random ) ?? Vector3 . Zero ) ; // TODO: Only calculated once per particle
74+
75+ return drift - ( velocity * friction ) ;
76+ } ,
77+ SpawnPosition = ( ) => component . SpawnPosition ? . GenerateVector3 ( _random ) ?? Vector3 . Zero ,
78+ SpawnVelocity = ( ) => component . SpawnVelocity ? . GenerateVector3 ( _random ) ?? Vector3 . Zero ,
79+ Transform = _ => { // TODO: Needs to only be performed every tick
80+ var scale = component . Scale . GenerateVector2 ( _random ) ;
81+ var rotation = component . Rotation ? . Generate ( _random ) ?? 0f ;
82+ var growth = component . Growth ? . GenerateVector2 ( _random ) ?? Vector2 . Zero ;
83+ var spin = component . Spin ? . Generate ( _random ) ?? 0f ;
7884 return Matrix3x2 . CreateScale ( scale . X + growth . X , scale . Y + growth . Y ) *
7985 Matrix3x2 . CreateRotation ( rotation + spin ) ;
8086 } ,
@@ -83,88 +89,4 @@ private ParticleSystemArgs GetParticleSystemArgs(DreamParticlesComponent compone
8389
8490 return result ;
8591 }
86-
87- private Func < float > GetGeneratorFloat ( float low , float high , GeneratorDistribution distribution ) {
88- switch ( distribution ) {
89- case GeneratorDistribution . Constant :
90- return ( ) => high ;
91- case GeneratorDistribution . Uniform :
92- return ( ) => _random . NextFloat ( low , high ) ;
93- case GeneratorDistribution . Normal :
94- return ( ) => ( float ) Math . Clamp ( _random . NextGaussian ( ( low + high ) / 2 , ( high - low ) / 6 ) , low , high ) ;
95- case GeneratorDistribution . Linear :
96- return ( ) => MathF . Sqrt ( _random . NextFloat ( 0 , 1 ) ) * ( high - low ) + low ;
97- case GeneratorDistribution . Square :
98- return ( ) => MathF . Cbrt ( _random . NextFloat ( 0 , 1 ) ) * ( high - low ) + low ;
99- default :
100- throw new NotImplementedException ( ) ;
101- }
102- }
103-
104- private Func < Vector2 > GetGeneratorVector2 ( Vector2 low , Vector2 high , GeneratorOutputType type , GeneratorDistribution distribution ) {
105- switch ( type ) {
106- case GeneratorOutputType . Num :
107- return ( ) => new Vector2 ( GetGeneratorFloat ( low . X , high . X , distribution ) ( ) , GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ) ;
108- case GeneratorOutputType . Vector :
109- return ( ) => Vector2 . Lerp ( low , high , GetGeneratorFloat ( 0 , 1 , distribution ) ( ) ) ;
110- case GeneratorOutputType . Box :
111- return ( ) => new Vector2 ( GetGeneratorFloat ( low . X , high . X , distribution ) ( ) , GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ) ;
112- case GeneratorOutputType . Circle :
113- var theta = _random . NextFloat ( 0 , 360 ) ;
114- //polar -> cartesian, radius between low and high, angle uniform sample
115- return ( ) => new Vector2 ( MathF . Cos ( theta ) * GetGeneratorFloat ( low . X , high . X , distribution ) ( ) , MathF . Sin ( theta ) * GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ) ;
116- case GeneratorOutputType . Square :
117- return ( ) => {
118- var x = GetGeneratorFloat ( - high . X , high . X , distribution ) ( ) ;
119- var y = GetGeneratorFloat ( - high . Y , high . Y , distribution ) ( ) ;
120- if ( MathF . Abs ( x ) < low . X )
121- y = _random . NextByte ( ) > 128
122- ? GetGeneratorFloat ( - high . Y , - low . Y , distribution ) ( )
123- : GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ;
124- return new ( x , y ) ;
125- } ;
126- default :
127- throw new NotImplementedException ( $ "Unimplemented generator output type { type } ") ;
128- }
129- }
130-
131- private Func < Vector3 > GetGeneratorVector3 ( Vector3 low , Vector3 high , GeneratorOutputType type , GeneratorDistribution distribution ) {
132- switch ( type ) {
133- case GeneratorOutputType . Num :
134- return ( ) => new Vector3 ( GetGeneratorFloat ( low . X , high . X , distribution ) ( ) , GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) , GetGeneratorFloat ( low . Z , high . Z , distribution ) ( ) ) ;
135- case GeneratorOutputType . Vector :
136- return ( ) => Vector3 . Lerp ( low , high , GetGeneratorFloat ( 0 , 1 , distribution ) ( ) ) ;
137- case GeneratorOutputType . Box :
138- return ( ) => new Vector3 ( GetGeneratorFloat ( low . X , high . X , distribution ) ( ) , GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) , GetGeneratorFloat ( low . Z , high . Z , distribution ) ( ) ) ;
139- case GeneratorOutputType . Sphere :
140- var theta = _random . NextFloat ( 0 , 360 ) ;
141- var phi = _random . NextFloat ( 0 , 180 ) ;
142- //3d polar -> cartesian, radius between low and high, angle uniform sample
143- return ( ) => new Vector3 (
144- MathF . Cos ( theta ) * MathF . Sin ( phi ) * GetGeneratorFloat ( low . X , high . X , distribution ) ( ) ,
145- MathF . Sin ( theta ) * MathF . Sin ( phi ) * GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ,
146- MathF . Cos ( phi ) * GetGeneratorFloat ( low . Z , high . Z , distribution ) ( )
147- ) ;
148- case GeneratorOutputType . Cube :
149- return ( ) => {
150- var x = GetGeneratorFloat ( - high . X , high . X , distribution ) ( ) ;
151- var y = GetGeneratorFloat ( - high . Y , high . Y , distribution ) ( ) ;
152- var z = GetGeneratorFloat ( - high . Z , high . Z , distribution ) ( ) ;
153- if ( MathF . Abs ( x ) < low . X )
154- y = _random . NextByte ( ) > 128
155- ? GetGeneratorFloat ( - high . Y , - low . Y , distribution ) ( )
156- : GetGeneratorFloat ( low . Y , high . Y , distribution ) ( ) ;
157- if ( MathF . Abs ( y ) < low . Y )
158- z = _random . NextByte ( ) > 128
159- ? GetGeneratorFloat ( - high . Z , - low . Z , distribution ) ( )
160- : GetGeneratorFloat ( low . Z , high . Z , distribution ) ( ) ;
161- return new ( x , y , z ) ;
162- } ;
163- case GeneratorOutputType . Circle :
164- case GeneratorOutputType . Square :
165- return ( ) => new Vector3 ( GetGeneratorVector2 ( new ( low . X , low . Y ) , new ( high . X , high . Y ) , type , distribution ) ( ) , 0 ) ;
166- default :
167- throw new NotImplementedException ( $ "Unimplemented generator output type { type } ") ;
168- }
169- }
17092}
0 commit comments