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