DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
EffectArea.c
Go to the documentation of this file.
1// Mostly used for better readability
3{
4 STATIC = 1,
5 DYNAMIC = 2
7
8// Class used for parameter transfer, all of the params are shadows of EffectArea member variables
9class EffectAreaParams
10{
11 string m_ParamName = "Default setup";
12 string m_ParamTriggerType = "ContaminatedTrigger";
13 float m_ParamRadius = 100;
14 float m_ParamPosHeight = 25;
15 float m_ParamNegHeight = 10;
18 bool m_ParamOuterToggle = true;
23 /*
24 int m_ParamPartId = ParticleList.CONTAMINATED_AREA_GAS_BIGASS;
25 int m_ParamAroundPartId = ParticleList.CONTAMINATED_AREA_GAS_AROUND;
26 int m_ParamTinyPartId = ParticleList.CONTAMINATED_AREA_GAS_TINY;
27 */
31
32 string m_ParamPpeRequesterType = "PPERequester_ContaminatedAreaTint";
33}
34
35// Base class for contaminated and other "Effect" areas
37{
38 // Area Data
39 string m_Name = "Default setup"; // The user defined name of the area
40 int m_Type = eZoneType.STATIC; // If the zone is static or dynamic
41 vector m_Position; // World position of Area
42
43 // Trigger Data
44 float m_Radius = 100; // Radius of the Contaminated Area
45 float m_PositiveHeight = 25; // Distance between center and maximum height
46 float m_NegativeHeight = 10; // Distance between center and minimum height
47
48 // PCG parameters
49 // Inner Particle data
50 int m_InnerRings = 1; // The amount of inner rings one wants
51 int m_InnerSpacing = 35; // Distance between two particles placed on inner rings of the area
52 // Outer particle data
53 bool m_OuterRingToggle = true; // Allow disabling outer ring if undesired
54 int m_OuterRingOffset = -5; // Distance between the outermost ring of particles and area radius
55 int m_OuterSpacing = 20; // Distance between two particles placed on the outer most ring of the area
56 // Verticality handling
57 int m_VerticalLayers = 0; // Used to add multiple layers vertically and set vertical spacing ( 0 don't do anything )
58 int m_VerticalOffset = 10; // Used to determine vertical offset between two vertical layers
59
60 // Particles and visual effects
66
67 // Other values and storage
68 string m_TriggerType = "ContaminatedTrigger"; // The trigger class used by this zone
69 CylinderTrigger m_Trigger; // The trigger used to determine if player is inside toxic area
70
71 ref array<Particle> m_ToxicClouds; // All static toxic clouds in ContaminatedArea
72
73 // ----------------------------------------------
74 // INITIAL SETUP
75 // ----------------------------------------------
76
78 {
79 RegisterNetSyncVariableFloat("m_Radius", 0, 0, 2);
80 RegisterNetSyncVariableFloat("m_PositiveHeight", 0, 0, 2);
81 RegisterNetSyncVariableFloat("m_NegativeHeight", 0, 0, 2);
82
83 RegisterNetSyncVariableInt("m_InnerRings");
84 RegisterNetSyncVariableInt("m_InnerSpacing");
85 RegisterNetSyncVariableInt("m_OuterRingOffset");
86 RegisterNetSyncVariableInt("m_OuterSpacing");
87 RegisterNetSyncVariableInt("m_VerticalLayers");
88 RegisterNetSyncVariableInt("m_VerticalOffset");
89
90 RegisterNetSyncVariableInt("m_ParticleID");
91 /*
92 RegisterNetSyncVariableInt("m_AroundParticleID");
93 RegisterNetSyncVariableInt("m_TinyParticleID");
94 RegisterNetSyncVariableInt("m_PPERequesterIdx");
95 */
96 RegisterNetSyncVariableBool("m_OuterRingToggle");
97 }
98
100 {
101
102 }
103
104 void SetupZoneData( EffectAreaParams params )
105 {
106 // A lot of branching, allowing to use default values on specified params
107 if ( params.m_ParamName != "" )
108 m_Name = params.m_ParamName;
109 if ( params.m_ParamTriggerType != "" )
110 m_TriggerType = params.m_ParamTriggerType;
111
112 if ( params.m_ParamRadius > 0 )
113 m_Radius = params.m_ParamRadius;
114 if ( params.m_ParamPosHeight > -1 )
115 m_PositiveHeight = params.m_ParamPosHeight;
116 if ( params.m_ParamNegHeight > -1 )
117 m_NegativeHeight = params.m_ParamNegHeight;
118
119 m_InnerRings = params.m_ParamInnerRings;
120 if ( params.m_ParamInnerSpace > -1 )
121 m_InnerSpacing = params.m_ParamInnerSpace;
122
123 m_OuterRingToggle = params.m_ParamOuterToggle;
124 if ( params.m_ParamOuterSpace > -1 )
125 m_OuterSpacing = params.m_ParamOuterSpace;
126 m_OuterRingOffset = params.m_ParamOuterOffset;
127
128 if ( params.m_ParamVertLayers > 0 )
129 m_VerticalLayers = params.m_ParamVertLayers;
130 if ( params.m_ParamVerticalOffset > 0 )
131 m_VerticalOffset = params.m_ParamVerticalOffset;
132
133 m_ParticleID = params.m_ParamPartId;
134 m_AroundParticleID = params.m_ParamAroundPartId;
135 m_TinyParticleID = params.m_ParamTinyPartId;
136
137 if ( params.m_ParamPpeRequesterType != "" )
138 {
139 m_PPERequesterType = params.m_ParamPpeRequesterType;
141 }
142 // We get the PPE index for future usage and synchronization
143
144
145 // DEVELOPER NOTE :
146 // If you cannot register a new requester, add your own indexation and lookup methods to get an index and synchronize it
147 // EXAMPLE : m_PPERequesterIdx = MyLookupMethod()
148
149 // We sync our data
150 SetSynchDirty();
151
152 // Now that everything is ready, we finalize setup
153 InitZone();
154 }
155
156 void Tick() {};
157
158
159 // Through this we will evaluate the resize of particles
160 override void OnCEUpdate()
161 {
162 super.OnCEUpdate();
163 Tick();
164 }
165
166 void InitZone()
167 {
168 //Debug.Log("------------------------------------------");
169 //Debug.Log( "We have created the zone : " + m_Name );
170
171 m_Position = GetWorldPosition();
172
173 if ( !GetGame().IsDedicatedServer() )
174 {
176 }
177
178 if ( GetGame().IsServer() )
179 {
181 }
182
183 //Debug.Log("------------------------------------------");
184 }
185
186 // The following methods are to be overriden to execute specifc logic
187 // Each method is executed where it says it will so no need to check for server or client ;)
188 void InitZoneServer() {};
189
190 void InitZoneClient() {};
191
192 // ----------------------------------------------
193 // INTERACTION SETUP
194 // ----------------------------------------------
195
196 override bool CanPutInCargo( EntityAI parent )
197 {
198 return false;
199 }
200
201 override bool CanPutIntoHands( EntityAI parent )
202 {
203 return false;
204 }
205
206 override bool DisableVicinityIcon()
207 {
208 return true;
209 }
210
211 override bool CanBeTargetedByAI( EntityAI ai )
212 {
213 return false;
214 }
215
216 // ----------------------------------------------
217 // PARTICLE GENERATION
218 // ----------------------------------------------
219 // Used to position all particles procedurally
220 void PlaceParticles( vector pos, float radius, int nbRings, int innerSpacing, bool outerToggle, int outerSpacing, int outerOffset, int partId )
221 {
222#ifdef NO_GUI
223 return; // do not place any particles if there is no GUI
224#endif
225 if (partId == 0)
226 {
227 Error("[WARNING] :: [EffectArea PlaceParticles] :: no particle defined, skipping area particle generation" );
228 return;
229 }
230 // Determine if we snap first layer to ground
231 bool snapFirstLayer = true;
232 if ( m_Type == eZoneType.STATIC && pos[1] != GetGame().SurfaceRoadY( pos[0], pos[2] ) )
233 snapFirstLayer = false;
234
235 // BEGINNING OF SAFETY NET
236 // We want to prevent divisions by 0
237 if ( radius == 0 )
238 {
239 // In specific case of radius, we log an error and return as it makes no sense
240 Error("[WARNING] :: [EffectArea PlaceParticles] :: Radius of contaminated zone is set to 0, this should not happen");
241 return;
242 }
243
244 if ( outerToggle && radius == outerOffset )
245 {
246 Error("[WARNING] :: [EffectArea PlaceParticles] :: Your outerOffset is EQUAL to your Radius, this will result in division by 0");
247 return;
248 }
249
250 // Inner spacing of 0 would cause infinite loops as no increment would happen
251 if ( innerSpacing == 0 )
252 innerSpacing = 1;
253
254 // END OF SAFETY NET
255
256 int partCounter = 0; // Used for debugging, allows one to know how many emitters are spawned in zone
257 int numberOfEmitters = 1; // We always have the central emitter
258
259 //Debug.Log("We have : " + nbRings + " rings");
260 //Debug.Log("We have : " + m_VerticalLayers + " layers");
261
262 float angle = 0; // Used in for loop to know where we are in terms of angle spacing ( RADIANS )
263
264 ParticlePropertiesArray props = new ParticlePropertiesArray();
265
266 // We also populate vertically, layer 0 will be snapped to ground, subsequent layers will see particles floating and relevant m_VerticalOffset
267 for ( int k = 0; k <= m_VerticalLayers; k++ )
268 {
269 vector partPos = pos;
270 // We prevent division by 0
271 // We don't want to tamper with ground layer vertical positioning
272 if ( k != 0 )
273 {
274 partPos[1] = partPos[1] + ( m_VerticalOffset * k );
275 }
276
277 // We will want to start by placing a particle at center of area
278 props.Insert(ParticleProperties(partPos, ParticlePropertiesFlags.PLAY_ON_CREATION, null, vector.Zero, this));
279 partCounter++;
280
281 // For each concentric ring, we place a particle emitter at a set offset
282 for ( int i = 1; i <= nbRings + outerToggle; i++ )
283 {
284 //Debug.Log("We are on iteration I : " + i );
285
286 // We prepare the variables to use later in calculation
287 float angleIncrement; // The value added to the offset angle to place following particle
288 float ab; // Length of a side of triangle used to calculate particle positionning
289 vector temp = vector.Zero; // Vector we rotate to position next spawn point
290
291 // The particle density is not the same on the final ring which will only happen if toggled
292 // Toggle uses bool parameter treated as int, thus i > nbRings test ( allows to limit branching )
293 if ( i > nbRings )
294 {
295 ab = radius - outerOffset; // We want to leave some space to better see area demarcation
296
297 // We calculate the rotation angle depending on particle spacing and distance from center
298 angleIncrement = Math.Acos( 1 - ( ( outerSpacing * outerSpacing ) / ( 2 * Math.SqrInt(ab) ) ) );
299 temp[2] = temp[2] + ab;
300
301 //Debug.Log("Radius of last circle " + i + " is : " + ab);
302 }
303 else
304 {
305 ab = ( radius / ( nbRings + 1 ) ) * i; // We add the offset from one ring to another
306
307 // We calculate the rotation angle depending on particle spacing and distance from center
308 angleIncrement = Math.Acos( 1 - ( ( innerSpacing * innerSpacing ) / ( 2 * Math.SqrInt(ab) ) ) );
309 temp[2] = temp[2] + ab;
310
311 //Debug.Log("Radius of inner circle " + i + " is : " + ab);
312 }
313
314 for ( int j = 0; j <= ( Math.PI2 / angleIncrement ); j++ )
315 {
316 // Determine position of particle emitter
317 // Use offset of current ring for vector length
318 // Use accumulated angle for vector direction
319
320 float sinAngle = Math.Sin( angle );
321 float cosAngle = Math.Cos( angle );
322
323 partPos = vector.RotateAroundZero( temp, vector.Up, cosAngle, sinAngle );
324 partPos += pos;
325
326 // We snap first layer to ground if specified
327 if ( k == 0 && snapFirstLayer == true )
328 partPos[1] = GetGame().SurfaceY( partPos[0], partPos[2] );
329 else if ( k == 0 && snapFirstLayer == false )
330 partPos[1] = partPos[1] - m_NegativeHeight;
331
332 // We check the particle is indeed in the trigger to make it consistent
333 if ( partPos[1] <= pos[1] + m_PositiveHeight && partPos[1] >= pos[1] - m_NegativeHeight )
334 {
335 // Place emitter at vector end ( coord )
336 props.Insert(ParticleProperties(partPos, ParticlePropertiesFlags.PLAY_ON_CREATION, null, GetGame().GetSurfaceOrientation( partPos[0], partPos[2] ), this));
337
338 ++partCounter;
339 }
340
341 // Increase accumulated angle
342 angle += angleIncrement;
343 }
344
345 angle = 0; // We reset our accumulated angle for the next ring
346 }
347 }
348
349 m_ToxicClouds.Reserve(partCounter);
350
351 ParticleManager gPM = ParticleManager.GetInstance();
352
353 array<ParticleSource> createdParticles = gPM.CreateParticlesByIdArr(partId, props, partCounter);
354 if (createdParticles.Count() != partCounter)
355 {
356 if (gPM.IsFinishedAllocating())
357 {
358 ErrorEx(string.Format("Not enough particles in pool for EffectArea: %1", m_Name));
359 OnParticleAllocation(gPM, createdParticles);
360 }
361 else
362 {
363 gPM.GetEvents().Event_OnAllocation.Insert(OnParticleAllocation);
364 }
365 }
366 else
367 {
368 OnParticleAllocation(gPM, createdParticles);
369 }
370
371 //Debug.Log("Emitter count : " + partCounter );
372 }
373
375 {
376 foreach (ParticleSource p : particles)
377 {
378 if (p.GetOwner() == this) // Safety, since it can be unrelated particles when done through event
379 m_ToxicClouds.Insert(p);
380 }
381 }
382
383 int GetRequesterIndex(string type)
384 {
385 typename t = type.ToType();
386 if (!t)
387 return - 1;
388 PPERequesterBase req = PPERequesterBank.GetRequester(t);
389 if (req)
390 return req.GetRequesterIDX();
391 return -1;
392 }
393
394
395 // ----------------------------------------------
396 // TRIGGER SETUP
397 // ----------------------------------------------
398
399 void CreateTrigger( vector pos, int radius )
400 {
401 // The trigger pos is based on lwer end, but we want to stretch downwards
402 pos[1] = pos[1] - m_NegativeHeight;
403
404 // Create new trigger of specified type
405 if ( Class.CastTo( m_Trigger, GetGame().CreateObjectEx( m_TriggerType, pos, ECE_NONE ) ) )
406 {
407 // We finalize trigger dimension setup
408 m_Trigger.SetCollisionCylinder( radius, ( m_NegativeHeight + m_PositiveHeight ) );
409
410 // If the trigger is lower in hierarchy and can see it's local effects customized, we pass the new parameters
411 if ( m_Trigger.IsInherited( EffectTrigger ) )
412 {
413 //Debug.Log("We override area local effects");
415 }
416
417 //Debug.Log("We created the trigger at : " + m_Trigger.GetWorldPosition() );
418 }
419 }
420
421 // ----------------------------------------------
422 // AREA DELETION
423 // ----------------------------------------------
424
425 override void EEDelete( EntityAI parent )
426 {
427 if ( m_Trigger )
428 {
430 }
431
432 // We stop playing particles on this client when the base object is deleted ( out of range for example )
433 if ( (GetGame().IsClient() || !GetGame().IsMultiplayer()) && m_ToxicClouds )
434 {
435 foreach ( Particle p : m_ToxicClouds )
436 {
437 p.Stop();
438 }
439 }
440
441 super.EEDelete( parent );
442 }
443}
const int ECE_NONE
int m_ParamVerticalOffset
Definition EffectArea.c:22
bool m_ParamOuterToggle
Definition EffectArea.c:18
int m_ParamPartId
Definition EffectArea.c:28
int m_ParamOuterOffset
Definition EffectArea.c:20
float m_ParamPosHeight
Definition EffectArea.c:14
string m_ParamTriggerType
Definition EffectArea.c:12
int m_ParamVertLayers
Definition EffectArea.c:21
int m_ParamTinyPartId
Definition EffectArea.c:30
string m_ParamPpeRequesterType
Definition EffectArea.c:32
float m_ParamRadius
Definition EffectArea.c:13
int m_ParamAroundPartId
Definition EffectArea.c:29
enum eZoneType m_ParamName
int m_ParamInnerSpace
Definition EffectArea.c:17
int m_ParamInnerRings
Definition EffectArea.c:16
int m_ParamOuterSpace
Definition EffectArea.c:19
eZoneType
Definition EffectArea.c:3
@ DYNAMIC
Definition EffectArea.c:5
@ STATIC
Definition EffectArea.c:4
float m_ParamNegHeight
Definition EffectArea.c:15
void ParticleManager(ParticleManagerSettings settings)
Constructor (ctor)
proto native void ObjectDelete(Object obj)
proto native float SurfaceY(float x, float z)
Super root of all classes in Enforce script.
Definition EnScript.c:11
Trigger with cylinder shape.
override bool DisableVicinityIcon()
Definition EffectArea.c:206
void InitZone()
Definition EffectArea.c:166
string m_TriggerType
Definition EffectArea.c:68
int m_InnerSpacing
Definition EffectArea.c:51
override void OnCEUpdate()
Definition EffectArea.c:160
void PlaceParticles(vector pos, float radius, int nbRings, int innerSpacing, bool outerToggle, int outerSpacing, int outerOffset, int partId)
Definition EffectArea.c:220
int m_VerticalOffset
Definition EffectArea.c:58
float m_NegativeHeight
Definition EffectArea.c:46
string m_Name
Definition EffectArea.c:39
override bool CanBeTargetedByAI(EntityAI ai)
Definition EffectArea.c:211
int m_TinyParticleID
Definition EffectArea.c:63
int m_OuterRingOffset
Definition EffectArea.c:54
bool m_OuterRingToggle
Definition EffectArea.c:53
int m_VerticalLayers
Definition EffectArea.c:57
int m_ParticleID
Definition EffectArea.c:61
override bool CanPutInCargo(EntityAI parent)
Definition EffectArea.c:196
ref array< Particle > m_ToxicClouds
Definition EffectArea.c:71
void CreateTrigger(vector pos, int radius)
Definition EffectArea.c:399
void InitZoneServer()
Definition EffectArea.c:188
int m_AroundParticleID
Definition EffectArea.c:62
override void EEDelete(EntityAI parent)
Definition EffectArea.c:425
float m_PositiveHeight
Definition EffectArea.c:45
void SetupZoneData(EffectAreaParams params)
Definition EffectArea.c:104
void OnParticleAllocation(ParticleManager pm, array< ParticleSource > particles)
Definition EffectArea.c:374
string m_PPERequesterType
Definition EffectArea.c:64
int m_OuterSpacing
Definition EffectArea.c:55
vector m_Position
Definition EffectArea.c:41
override bool CanPutIntoHands(EntityAI parent)
Definition EffectArea.c:201
void ~EffectArea()
Definition EffectArea.c:99
CylinderTrigger m_Trigger
Definition EffectArea.c:69
int m_PPERequesterIdx
Definition EffectArea.c:65
int GetRequesterIndex(string type)
Definition EffectArea.c:383
void EffectArea()
Definition EffectArea.c:77
int m_InnerRings
Definition EffectArea.c:50
void Tick()
Definition EffectArea.c:156
float m_Radius
Definition EffectArea.c:44
void InitZoneClient()
Definition EffectArea.c:190
void SetLocalEffects(int aroundPartId, int tinyPartId, int ppeRequesterIdx)
Definition EnMath.c:7
int GetRequesterIDX()
Returns requester index.
Legacy way of using particles in the game.
Definition Particle.c:7
static const int CONTAMINATED_AREA_GAS_TINY
static const int CONTAMINATED_AREA_GAS_AROUND
static const int CONTAMINATED_AREA_GAS_BIGASS
Entity which has the particle instance as an ObjectComponent.
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
static vector RotateAroundZero(vector pos, vector axis, float cosAngle, float sinAngle)
Rotate a vector around 0,0,0.
Definition EnConvert.c:477
static const vector Up
Definition EnConvert.c:107
static const vector Zero
Definition EnConvert.c:110
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition EnDebug.c:90
enum ShapeType ErrorEx
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
static proto float Acos(float c)
Returns angle in radians from cosinus.
static proto float Cos(float angle)
Returns cosinus of angle in radians.
static proto int SqrInt(int i)
Returns squared value.
static const float PI2
Definition EnMath.c:13
static proto float Sin(float angle)
Returns sinus of angle in radians.
proto native ToType()
Returns internal type representation. Can be used in runtime, or cached in variables and used for fas...