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