Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
particle.c
Go to the documentation of this file.
2{
3 protected int m_ParticleID;
4 protected float m_Lifetime;
5 protected int m_PreviousFrame;
6 protected bool m_IsPlaying;
7 protected bool m_IsRepeat;
8 private bool m_MarkedForDeletion;
9 bool m_ForceOrientationRelativeToWorld = false;
10 vector m_DefaultOri;
11 vector m_DefaultPos;
12 float m_MaxOriWiggle;
13 float m_MaxOriInterval;
14 ref Timer m_RandomizeOri;
15
16 private Object m_ParentObject; // TO DO: Remove m_ParentObject parameter and use GetObject instead!
18
19 private vector m_GlobalPosPreviousFrame;
20
21 static private const int MAX_EMITORS = 30; // Limits the amount of emitors this API works with. Increase in case of need.
22
23
24 //====================================
25 // Client: Constructor
26 //====================================
27 void Particle()
28 {
29 SetFlags(EntityFlags.VISIBLE, true);
30 SetEventMask(EntityEvent.INIT);
31 SetEventMask(EntityEvent.FRAME);
32 }
33
34 //====================================
35 // Client: UpdateState
36 //====================================
37 protected void UpdateState()
38 {
39 if ( m_IsPlaying == false && m_ParticleEffect)
40 {
41 DestroyParticleEffect();
42 }
43 else if ( m_IsPlaying == true && m_ParticleEffect == NULL )
44 {
45 CreateParticleEffect();
46 }
47 }
48
50 {
51 return m_ParentObject;
52 }
53
54 override bool IsParticle()
55 {
56 return true;
57 }
58
59 //====================================
60 // Client: CreateParticleEffect
61 //====================================
62 private void CreateParticleEffect()
63 {
64 if (!GetGame().IsServer() || !GetGame().IsMultiplayer())
65 {
66 if ( m_ParticleEffect == NULL )
67 {
68 m_ParticleEffect = GetGame().CreateObject("#particlesourceenf", Vector(0,0,0), true); // particle source must be lowercase!
69 }
70
71 this.AddChild(m_ParticleEffect, -1, m_ForceOrientationRelativeToWorld);
72 vobject vobj = NULL;
73
74 vobj = GetObject( ParticleList.GetParticleFullPath(m_ParticleID) );
75
76 m_ParticleEffect.SetObject(vobj, "");
77 ReleaseObject(vobj);
78
81 }
82 }
83
84 float GetMaxLifetime()
85 {
87 {
88 float lifetime_min = 0;
89 float lifetime_random = 0;
90 float lifetime_return = 0;
91 float effect_time = 0;
92 string emitors_array[MAX_EMITORS];
93
94 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
95
96 for (int i = 0; i < emitors; i++)
97 {
98 GetParticleParm(m_ParticleEffect, i, EmitorParam.LIFETIME, lifetime_min);
99 GetParticleParm(m_ParticleEffect, i, EmitorParam.LIFETIME_RND, lifetime_random);
100 GetParticleParm(m_ParticleEffect, i, EmitorParam.EFFECT_TIME, effect_time);
101
102 if ( lifetime_min + lifetime_random + effect_time > lifetime_return )
103 {
104 lifetime_return = lifetime_min + lifetime_random + effect_time;
105 }
106 }
107 }
108
109 return lifetime_return;
110 }
111
114 {
115 return m_ParticleEffect;
116 }
117
118 //====================================
119 // Client: DestroyParticleEffect
120 //====================================
121 private void DestroyParticleEffect()
122 {
123 if ( m_ParticleEffect && GetGame() )
124 {
125 SetParameter(-1, EmitorParam.LIFETIME, 0);
126 SetParameter(-1, EmitorParam.LIFETIME_RND, 0);
127 SetParameter(-1, EmitorParam.REPEAT, 0);
128
129 m_IsRepeat = false;
130
131 // Particle is now disabled. The EOnFrame event will delete it from the world when all of its particles are despawned.
132 }
133 }
134
135 //====================================
136 // Client: SetParameter
137 //====================================
138 void SetParameter(int emitter, int parameter, float value)
139 {
140 // m_ParticleEffect -> owner of Particle, as set in Particle CreateParticleEffect()
141
142 SetParticleParm(m_ParticleEffect, emitter, parameter, value);
143 }
144
145 //====================================
146 // Client: GetParameter
147 //====================================
148 void GetParameter(int emitter, int parameter, out float value)
149 {
150 // m_ParticleEffect -> owner of Particle, as set in Particle CreateParticleEffect()
151
152 GetParticleParm(m_ParticleEffect, emitter, parameter, value);
153 }
154
155 //====================================
156 // Client: GetParticleCount
157 // Warning! CPU expensive!
158 //====================================
159 int GetParticleCount()
160 {
162 {
163 return m_ParticleEffect.GetParticleCount(m_ParticleEffect);
164 }
165
166 return 0;
167 }
168
169 //====================================
170 // Client: IsRepeat()
171 // Warning! CPU expensive!
172 //====================================
173 bool IsRepeat()
174 {
176 {
177 int repeat = false;
178 string emitors_array[MAX_EMITORS];
179
180 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
181
182 for (int i = 0; i < emitors; i++)
183 {
184 GetParticleParm(m_ParticleEffect, i, EmitorParam.REPEAT, repeat);
185
186 if (repeat)
187 {
188 return true;
189 }
190 }
191 }
192
193 return false;
194 }
195
196 // !Scales the given parameter on all emitors relatively to their ORIGINAL value. If you want to change a specific emitor, then use function SetParticleParm().
197 void ScaleParticleParamFromOriginal(int parameter_id, float coef )
198 {
200 {
201 string emitors_array[MAX_EMITORS];
202
203 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
204
205 for (int i = 0; i < emitors; i++)
206 {
207 float value
208 GetParticleParmOriginal (m_ParticleEffect, i, parameter_id, value);
209 SetParticleParm (m_ParticleEffect, i, parameter_id, value * coef);
210 }
211 }
212 }
213
214 // !Scales the given parameter on all emitors relatively to their CURRENT value. If you want to change a specific emitor, then use function SetParticleParm().
215 void ScaleParticleParam(int parameter_id, float coef )
216 {
218 {
219 string emitors_array[MAX_EMITORS];
220
221 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
222
223 for (int i = 0; i < emitors; i++)
224 {
225 float value
226 GetParticleParm(m_ParticleEffect, i, parameter_id, value);
227 SetParticleParm(m_ParticleEffect, i, parameter_id, value * coef);
228 }
229 }
230 }
231
232 // !Increments the value of the given parameter relatively from the ORIGINAL value. Use negative number to decrement value.
233 void IncrementParticleParamFromOriginal(int parameter_id, float value )
234 {
236 {
237 string emitors_array[MAX_EMITORS];
238
239 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
240
241 for (int i = 0; i < emitors; i++)
242 {
243 float param
244 GetParticleParm(m_ParticleEffect, i, parameter_id, param);
245 SetParticleParm(m_ParticleEffect, i, parameter_id, param + value);
246 }
247 }
248 }
249
250 // !Increments the value of the given parameter relatively from the CURRENT value. Use negative number to decrement value.
251 void IncrementParticleParam(int parameter_id, float value )
252 {
254 {
255 string emitors_array[MAX_EMITORS];
256
257 int emitors = GetParticleEmitors(m_ParticleEffect, emitors_array, MAX_EMITORS);
258
259 for (int i = 0; i < emitors; i++)
260 {
261 float param
262 GetParticleParm(m_ParticleEffect, i, parameter_id, param);
263 SetParticleParm(m_ParticleEffect, i, parameter_id, param + value);
264 }
265 }
266 }
267
268 // !Scale some parameter for all emitors in this particle effect. If you want to change a specific emitor, then use function SetParticleParm().
269 void SetParticleParam(int parameter_id, float value )
270 {
271 SetParticleParm(m_ParticleEffect, -1, parameter_id, value);
272 }
273
274
275 //====================================
276 // Client: OnCheckAutoDelete
277 //====================================
278 void OnCheckAutoDelete()
279 {
280 if (m_Lifetime <= 0)
281 {
282 if (!m_MarkedForDeletion)
283 {
284 m_IsRepeat = IsRepeat(); // It is possible that the REPEAT flag was changed during lifetime, so it needs to be checked again.
285
286 if ( m_IsRepeat )
287 {
289 }
290 else
291 {
292 m_IsPlaying = false;
293
294 if ( GetParticleCount() == 0 )
295 {
296 m_MarkedForDeletion = true;
297 OnToDelete();
298 }
299 }
300 }
301 else
302 {
303 if ( m_MarkedForDeletion )
304 {
305 GetGame().ObjectDelete( m_ParticleEffect );
306 m_ParticleEffect = NULL;
307 GetGame().ObjectDelete( this );
308 }
309 }
310 }
311 }
312
313 override void EOnFrame(IEntity other, float timeSlice)
314 {
315 super.EOnFrame(other, timeSlice);
316
317 m_Lifetime -= timeSlice;
318
319 // WIP experiment with measurements of particle's speed.
320 /*EntityAI parent = EntityAI.Cast( GetParent() ); // THIS SHOULD BE IEntity kind! Do not cast here if not necesarry!
321
322 if (parent)
323 {
324 if ( m_GlobalPosPreviousFrame == Vector(0,0,0) )
325 {
326 m_GlobalPosPreviousFrame = GetPosition();
327 return;
328 }
329
330 if ( m_PreviousFrame == 0 )
331 {
332 m_PreviousFrame = GetGame().GetTime();
333 return;
334 }
335
336 vector global_pos_now = GetPosition();
337
338 float distance_per_frame = vector.Distance(global_pos_now, m_GlobalPosPreviousFrame);
339 int lag = GetGame().GetTime() - m_PreviousFrame;
340 float stretch = distance_per_frame * lag;
341
342 if ( parent.GetType() == "Torch" )
343 Print(stretch);
344
345 m_GlobalPosPreviousFrame = GetPosition();
346 }*/
347
348 OnCheckAutoDelete();
349 }
350
351 // Called before deletion
352 private void OnToDelete()
353 {
354
355
356
357 /* TODO Call Back To Effect
358 if (m_MyEffectHolder)
359 {
360 if ( m_MyEffectHolder.GetParticle() == this )
361 {
362 m_MyEffectHolder.SetParticle(NULL);
363 m_MyEffectHolder.CheckLifeSpan();
364 }
365 }
366 */
367 }
368
370 void SetWiggle(float random_angle, float random_interval)
371 {
372 if ( !random_angle == 0 || !random_interval == 0)
373 {
374 m_MaxOriWiggle = random_angle;
375 m_MaxOriInterval = random_interval;
376
377 if (!m_RandomizeOri)
378 m_RandomizeOri = new Timer( CALL_CATEGORY_GAMEPLAY );
379
380 if ( !m_RandomizeOri.IsRunning() ) // Makes sure the timer is NOT running already
381 {
382 m_RandomizeOri.Run( Math.RandomFloat(0, m_MaxOriInterval) , this, "RandomizeOrientation", NULL, false);
383 }
384 }
385 else if (m_RandomizeOri)
386 {
387 m_RandomizeOri.Stop();
388 delete m_RandomizeOri;
389 }
390 }
391
393 void StopWiggle()
394 {
395 SetWiggle(0,0);
396 }
397
398 // Randomizes orientation within m_MaxOriWiggle
399 void RandomizeOrientation()
400 {
401 if (m_ParentObject)
402 {
403 if ( !m_RandomizeOri.IsRunning() )
404 {
405 m_RandomizeOri.Run( Math.RandomFloat(0, m_MaxOriInterval) , this, "RandomizeOrientation", NULL, false);
406 }
407
408 Object old_parent = m_ParentObject;
409 AddAsChild( NULL );
410
411 float r1 = Math.RandomFloat(0, m_MaxOriWiggle*2) - m_MaxOriWiggle;
412 float r2 = Math.RandomFloat(0, m_MaxOriWiggle*2) - m_MaxOriWiggle;
413 float r3 = Math.RandomFloat(0, m_MaxOriWiggle*2) - m_MaxOriWiggle;
414
415 vector new_ori = m_DefaultOri + Vector( r1, r2, r3 );
416 AddAsChild( old_parent, m_DefaultPos, new_ori );
417 }
418 }
419
432 static Particle CreateOnObject( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_world_rotation = false )
433 {
434 if (!parent_obj)
435 Error("ERROR when creating a particle! Parameter parent_obj is NULL!");
436
437 vector global_pos = parent_obj.GetPosition();
438 Particle p = CreateInWorld(particle_id, global_pos, Vector(0,0,0), force_world_rotation);
439 p.AddAsChild(parent_obj, local_pos, local_ori, force_world_rotation);
440 p.m_DefaultOri = local_ori;
441
442 return p;
443 }
444
446 static Particle Create( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0" )
447 {
448 return CreateOnObject( particle_id, parent_obj, local_pos, local_ori);
449 }
450
458 static Particle CreateInWorld( int particle_id, vector global_pos, vector global_ori = "0 0 0", bool force_world_rotation = false )
459 {
460 if ( !GetGame().IsServer() || !GetGame().IsMultiplayer() )
461 {
462 Particle p = Particle.Cast( GetGame().CreateObject("Particle", global_pos, true) );
464 p.SetOrientation(global_ori);
465 p.m_ForceOrientationRelativeToWorld = force_world_rotation;
466 return p;
467 }
468 else
469 {
470 Error("A particle was spawned on server-side! Particles can be spawned on client-side only!");
471 }
472
473 return null;
474 }
475
477 static Particle Create( int particle_id, vector global_pos, vector global_ori = "0 0 0" )
478 {
479 return CreateInWorld( particle_id, global_pos, global_ori );
480 }
481
482
483
498 static Particle PlayOnObject( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_world_rotation = false )
499 {
500 Particle p = CreateOnObject(particle_id, parent_obj, local_pos, local_ori, force_world_rotation);
501 p.PlayParticle();
502
503 return p;
504 }
505
507 static Particle Play( int particle_id, Object parent_obj, vector local_pos = "0 0 0", vector local_ori = "0 0 0" )
508 {
509 return PlayOnObject( particle_id, parent_obj, local_pos, local_ori);
510 }
511
518 static Particle PlayInWorld( int particle_id, vector global_pos)
519 {
520 Particle p = CreateInWorld(particle_id, global_pos);
521 p.PlayParticle();
522
523 return p;
524 }
525
527 static Particle Play( int particle_id, vector global_pos)
528 {
529 return PlayInWorld( particle_id, global_pos);
530 }
531
533 void PlayParticle(int particle_id = -1)
534 {
535 if ( particle_id > -1 )
536 {
538 }
539
540 m_IsPlaying = true;
541
542 UpdateState();
543 }
544
546 void Play(int particle_id = -1)
547 {
549 }
550
552 void Stop()
553 {
554 m_IsPlaying = false;
555
556
557 // Without the following we might get an error when a particle parent is despawned client-side.
558 Object parent = Object.Cast( GetParent() );
559 if( parent )
560 {
561 vector world_pos = GetPosition();
562 parent.RemoveChild(this);
563 SetPosition(world_pos);
564 }
565
566 UpdateState();
567 }
568
575 void AddAsChild(Object parent, vector local_pos = "0 0 0", vector local_ori = "0 0 0", bool force_rotation_to_world = false)
576 {
577 if (parent && !parent.ToDelete()) // AddAsChild method is sometimes called from a timer. Due to that it is necesarry to use ToDelete() here to check if the parent object is flagged for deletion or not on client, because sometimes this code is executed before the parent's destructor from where this would normally be handled.
578 {
579 SetPosition(local_pos);
580 SetOrientation(local_ori);
581 m_ParentObject = parent;
582 m_DefaultPos = local_pos;
583 m_ForceOrientationRelativeToWorld = force_rotation_to_world;
584
586 AddChild(m_ParticleEffect, -1, m_ForceOrientationRelativeToWorld);
587
588 parent.AddChild(this, -1, false); // Pivot does not work in DayZ so we use -1.
589 }
590 else
591 {
592 if (m_ParentObject && !m_ParentObject.ToDelete())
593 {
594 m_ParentObject.RemoveChild(this);
595 SetPosition( m_ParentObject.ModelToWorld( GetPosition() ) ); // Move the detached particle to its last position on the parent. Otherwise it will be around [0,0,0].
596 m_ParentObject = NULL;
597 }
598 }
599 }
600
602 void SetSource(int particle_id)
603 {
605 }
606
608 int GetParticleID()
609 {
610 return m_ParticleID;
611 }
612}
Definition enmath.c:7
Legacy way of using particles in the game.
Definition particle.c:7
bool m_IsRepeat
Whether this particle repeats.
Definition particle.c:17
static Particle Create(int particle_id, Object parent_obj, vector local_pos="0 0 0", vector local_ori="0 0 0")
Legacy function for backwards compatibility.
Definition particle.c:104
float GetMaxLifetime()
Returns the approx. max lifetime.
Definition particle.c:380
static Particle PlayOnObject(int particle_id, Object parent_obj, vector local_pos="0 0 0", vector local_ori="0 0 0", bool force_world_rotation=false)
Creates a particle emitter, attaches it on the given object and activates it.
Definition particle.c:152
Object m_ParticleEffect
The child object which contains the actual particle.
Definition particle.c:50
static Particle CreateInWorld(int particle_id, vector global_pos, vector global_ori="0 0 0", bool force_world_rotation=false)
Creates a particle emitter on the given position.
Definition particle.c:117
int GetParticleCount()
Returns the total count of active particles in all emitors.
Definition particle.c:340
static Particle PlayInWorld(int particle_id, vector global_pos)
Creates a particle emitter on the given position and activates it.
Definition particle.c:174
void SetSource(int particle_id)
Sets particle id.
Definition particle.c:285
override void PlayParticle(int particle_id=-1)
Method to tell the particle to start playing.
Definition particle.c:203
static Particle CreateOnObject(int particle_id, Object parent_obj, vector local_pos="0 0 0", vector local_ori="0 0 0", bool force_world_rotation=false)
Creates a particle emitter and attaches it on the given object.
Definition particle.c:88
int GetParticleID()
Gets particle id.
Definition particle.c:297
float m_Lifetime
Approx. remaining lifetime of particle.
Definition particle.c:15
Object m_ParentObject
Parent Object the Particle is child of.
Definition particle.c:48
int m_ParticleID
ID from ParticleList if assigned.
Definition particle.c:13
bool IsRepeat()
Returns whether there is a repeating particle.
Definition particle.c:354
void UpdateState()
Creates/Destroys ParticleEffect child according to current state.
Definition particle.c:425
void Stop()
Legacy function for backwards compatibility with 1.14 and below.
Definition particle.c:266
Object GetDirectParticleEffect()
Returns direct particle effect entity which is usually handled by this class 'Particle' if there is o...
Definition particle.c:307
override bool IsParticle()
Definition particle.c:54
void UpdateState()
Definition particle.c:37
float m_Lifetime
Definition particle.c:4
bool m_IsPlaying
Definition particle.c:6
int m_ParticleID
Definition particle.c:3
int m_PreviousFrame
Definition particle.c:5
bool m_IsRepeat
Definition particle.c:7
Object GetParticleParent()
Definition particle.c:49
bool m_IsPlaying
Whether the Effect is currently playing.
Definition effect.c:37
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition endebug.c:90
proto native void SetPosition(vector position)
Set the world position of the Effect.
Definition effect.c:463
proto native void SetFlags(ShapeFlags flags)
EntityEvent
Entity events for event-mask, or throwing event from code.
Definition enentity.c:45
EntityFlags
Entity flags.
Definition enentity.c:115
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
proto void SetParticleParm(notnull IEntity ent, int emitor, EmitorParam parameter, void value)
proto void GetParticleParmOriginal(notnull IEntity ent, int emitor, EmitorParam parameter, out void value)
proto int GetParticleEmitors(notnull IEntity ent, out string emitors[], int max)
EmitorParam
Definition envisual.c:114
proto void GetParticleParm(notnull IEntity ent, int emitor, EmitorParam parameter, out void value)
proto void Play()
class JsonUndergroundAreaTriggerData GetPosition
const int CALL_CATEGORY_GAMEPLAY
Definition tools.c:10
proto native vobject GetObject(string name)
Loads object from data, or gets it from cache. Object must be released when not used.
proto native void ReleaseObject(vobject object, int flag=0)
int particle_id