Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_RandomPositionalSounds.c
Go to the documentation of this file.
2 {
6  SEA,
7  POND,
8 }
9 
15 [BaseContainerProps(configRoot: true)]
16 class SCR_RandomPositionalSounds : SCR_AmbientSoundsEffect
17 {
18  [Attribute()]
19  private ref array<ref SCR_RandomPositionalSoundsDef> m_aRandomPositionalSoundsDef;
20 
21  [Attribute("", UIWidgets.ResourceNamePicker, desc: "SoundInfo to ambient groups selector config", params: "conf")]
22  private ResourceName m_TerrainDefinitionResource;
23 
24  [Attribute("", UIWidgets.ResourceNamePicker, desc: "Daytime curves config", params: "conf")]
25  private ResourceName m_DayTimeCurveResource;
26 
27  [Attribute("", UIWidgets.ResourceNamePicker, desc: "Wind modifier curves config", params: "conf")]
28  private ResourceName m_WindCurveResource;
29 
30  // Configuration
31  private ref array<ref SCR_SoundGroup> m_aSoundGroup = {};
32  private ref array<ref SCR_SpawnDef> m_aSpawnDef = {};
33  private ref array<ref SCR_TerrainDef> m_aTerrainDef;
34  private ref array<ref SCR_DayTimeCurveDef> m_aDayTimeCurve;
35  private ref array<ref SCR_WindCurveDef> m_aWindModifier;
36 
37  // Components
38  private GameSignalsManager m_GlobalSignalsManager;
39  private ChimeraWorld m_World;
40  private SoundWorld m_SoundWorld;
41 
42  // Constants
43  private const int INVALID = -1;
44  private const int TREE_LEAFY_HEIGHT_LIMIT = 10;
45  private const int TREE_CONIFER_HEIGHT_LIMIT = 12;
46  private const int LAKE_AREA_LIMIT = 100000;
47  private const int COAST_HIGHT_LIMIT = 3;
48  private const int GLOBAL_MODIFIERS_UPDATE_TIME = 10000;
49  private const string SUN_ANGLE_SIGNAL_NAME = "SunAngle";
50  private const string SOUND_NAME_SIGNAL_NAME = "SoundName";
51  private const string DISTANCE_SIGNAL_NAME = "Distance";
52  private const string RAIN_INTENSITY_SIGNAL_NAME = "RainIntensity";
53  private const string WIND_SPEED_SIGNAL_NAME = "WindSpeed";
54  private const string ENVIRONMENT_TYPE_SIGNAL_NAME = "EnvironmentType";
55 
56  // Signal Idxs
57  private int m_iSunAngleSignalIdx;
58  private int m_iSoundNameSignalIdx;
59  private int m_iDistanceSignalIdx;
60  private int m_iRainIntensitySignalIdx;
61  private int m_iWindSpeedSignalIdx;
62  private int m_iEnvironmentTypeSignalIdx;
63 
64  private int m_iUpdatedSoundGroupIdx;
65  private int m_iEnvironmentTypeSignalValue;
66  private float m_fGlobalModifiersTimer;
67  private ref array<int> m_aDensity = {};
68  private ref array<float> m_aDensityModifier = {};
69  private ref array<int> m_aAngleOffset = {};
70  private float m_aDayTimeCurveValue[DAY_TIME_CURVE_COUNT];
71  private float m_aWindCurveValue[WIND_CURVE_COUNT];
72 
73  private ref array<ref SCR_SoundHandle> m_aSoundHandle = {};
74 
75  //------------------------------------------------------------------------------------------------
76  // Called by SCR_AmbientSoundComponent in UpdateSoundJob()
77  override void Update(float worldTime, vector cameraPos)
78  {
79  // Get environment type
80  m_iEnvironmentTypeSignalValue = m_LocalSignalsManager.GetSignalValue(m_iEnvironmentTypeSignalIdx);
81 
82  ProcessSoundGroups(worldTime, cameraPos);
83  UpdateSoundSequence(worldTime, cameraPos);
84 
85  if (worldTime > m_fGlobalModifiersTimer)
86  {
87  UpdateGlobalModifiers();
88  RemoveSoundsBasedOnTimeAndWeather();
89  m_fGlobalModifiersTimer = worldTime + GLOBAL_MODIFIERS_UPDATE_TIME;
90  }
91  }
92 
93 #ifdef ENABLE_DIAG
94  //------------------------------------------------------------------------------------------------
95  override void UpdateDebug(float worldTime)
96  {
97  if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS))
98  {
99  AmbientSignalsDebug();
100  RandomPositionalSoundDebug(worldTime);
101  DensityDebug();
102  PlaySound(worldTime);
103  }
104  }
105 #endif
106 
107  //------------------------------------------------------------------------------------------------
108  private void ProcessSoundGroups(float worldTime, vector cameraPos)
109  {
110  UpdateSoundGroup(worldTime, cameraPos, m_iUpdatedSoundGroupIdx);
111 
112  m_iUpdatedSoundGroupIdx ++;
113  if (m_iUpdatedSoundGroupIdx < m_aSoundGroup.Count())
114  return;
115 
116  m_iUpdatedSoundGroupIdx = 0;
117 
118  RemoveOutOfRangeSound(cameraPos);
119  UpdateDensity();
120  }
121 
122  //------------------------------------------------------------------------------------------------
124  private void RemoveSoundsBasedOnTimeAndWeather()
125  {
126  for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
127  {
128  SCR_SoundHandle soundHandle = m_aSoundHandle[i];
129 
130  if (m_aDayTimeCurveValue[soundHandle.m_SoundDef.m_eDayTimeCurve] == 0 || m_aDensityModifier[soundHandle.m_iSoundGroup] == 0)
131  m_aSoundHandle.Remove(i);
132  }
133  }
134 
135  //------------------------------------------------------------------------------------------------
137  private void UpdateGlobalModifiers()
138  {
139  //Update values of wind modifiers curves
140  float windSpeedScaled = Interpolate01(m_GlobalSignalsManager.GetSignalValue(m_iWindSpeedSignalIdx), SCR_AmbientSoundsComponent.WINDSPEED_MIN, SCR_AmbientSoundsComponent.WINDSPEED_MAX);
141  for (int i = 0; i < WIND_CURVE_COUNT; i++)
142  {
143  m_aWindCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(windSpeedScaled, m_aWindModifier[i].m_Curve);
144  }
145 
146  float timeOfDay = m_LocalSignalsManager.GetSignalValue(m_iSunAngleSignalIdx) / 360;
147 
148  foreach (int i, SCR_SpawnDef spawnDef : m_aSpawnDef)
149  {
150  float modifier = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, spawnDef.m_TimeModifier);
151  modifier = modifier * SCR_AmbientSoundsComponent.GetPoint(m_GlobalSignalsManager.GetSignalValue(m_iRainIntensitySignalIdx), spawnDef.m_RainModifier);
152  m_aDensityModifier[i] = modifier * m_aWindCurveValue[spawnDef.m_eWindModifier];
153  }
154 
155  // Update values of day time curves
156  for (int i = 0; i < DAY_TIME_CURVE_COUNT; i++)
157  {
158  m_aDayTimeCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, m_aDayTimeCurve[i].m_Curve);
159  }
160  }
161 
162  //------------------------------------------------------------------------------------------------
163  private int GetDensityMax(int soundGroup)
164  {
165  if (m_iEnvironmentTypeSignalValue == EEnvironmentType.MEADOW)
166  return m_aSpawnDef[soundGroup].m_iMeadowDensityMax;
167  else if (m_iEnvironmentTypeSignalValue == EEnvironmentType.FOREST)
168  return m_aSpawnDef[soundGroup].m_iForestDensityMax;
169  else if (m_iEnvironmentTypeSignalValue == EEnvironmentType.HOUSES)
170  return m_aSpawnDef[soundGroup].m_iHousesDensityMax;
171  else
172  return m_aSpawnDef[soundGroup].m_iSeaDensityMax;
173  }
174 
175  //------------------------------------------------------------------------------------------------
176  private void UpdateSoundSequence(float worldTime, vector cameraPos)
177  {
178  for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
179  {
180  SCR_SoundHandle soundHandle = m_aSoundHandle[i];
181 
182  if (worldTime > soundHandle.m_aRepTime[soundHandle.m_iRepTimeIdx])
183  {
184  // Set SoundName signal
185  if (m_iSoundNameSignalIdx != INVALID)
186  m_LocalSignalsManager.SetSignalValue(m_iSoundNameSignalIdx, soundHandle.m_SoundDef.m_eSoundName);
187 
188  // Set Distance signal
190  m_LocalSignalsManager.SetSignalValue(m_iDistanceSignalIdx, vector.Distance(cameraPos, soundHandle.m_aMat[3]));
191 
192  // Play sound event
193  m_AmbientSoundsComponent.SoundEventTransform(m_aSoundGroup[soundHandle.m_iSoundGroup].m_sSoundEvent, soundHandle.m_aMat);
194 
195 #ifdef ENABLE_DIAG
196  soundHandle.m_SoundDef.m_iCount++;
197 #endif
198 
199  // Remove if last event in the sequence
200  soundHandle.m_iRepTimeIdx ++;
201  if (soundHandle.m_aRepTime.Count() == soundHandle.m_iRepTimeIdx)
202  m_aSoundHandle.Remove(i);
203  }
204  }
205  }
206 
207  //------------------------------------------------------------------------------------------------
208  private void RemoveOutOfRangeSound(vector cameraPos)
209  {
210  for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
211  {
212  SCR_SoundHandle soundHandle = m_aSoundHandle[i];
213  SCR_SpawnDef spawnDef = m_aSpawnDef[soundHandle.m_iSoundGroup];
214 
215  if (!Math.IsInRange(vector.Distance(cameraPos, soundHandle.m_aMat[3]), spawnDef.m_iPlayDistMin, spawnDef.m_iPlayDistMax))
216  m_aSoundHandle.Remove(i);
217  }
218  }
219 
220  //------------------------------------------------------------------------------------------------
225  private void UpdateSoundGroup(float worldTime, vector camPos, int soundGroup)
226  {
227  // Check if density modified by rain, wind and time of day was reached
228  if (m_aDensity[soundGroup] >= GetDensityMax(soundGroup) * m_aDensityModifier[soundGroup])
229  return;
230 
231  // Generate sound position
232  vector vPos;
233  int soundType = INVALID;
234 
235  ESpawnMethod spawhMethod = m_aSoundGroup[soundGroup].m_eSpawnMethod;
236 
237  if (spawhMethod == ESpawnMethod.ENTITY)
238  {
239  // Choose dominant tree type
240  ETreeSoundTypes treeSoundType = m_AmbientSoundsComponent.GetDominantTree();
241  if (treeSoundType == EQueryType.TreeConifer)
242  {
243  IEntity tree = m_AmbientSoundsComponent.GetRandomTree(EQueryType.TreeConifer, TREE_CONIFER_HEIGHT_LIMIT);
244  if (!tree)
245  return;
246 
247  soundType = 0;
248  vPos = GetRandomPositionOnEntity(tree);
249  }
250  else if (treeSoundType == EQueryType.TreeLeafy)
251  {
252  IEntity tree = m_AmbientSoundsComponent.GetRandomTree(EQueryType.TreeLeafy, TREE_LEAFY_HEIGHT_LIMIT);
253  if (!tree)
254  return;
255 
256  soundType = 1;
257  vPos = GetRandomPositionOnEntity(tree);
258  }
259  }
260  else if (spawhMethod == ESpawnMethod.TERRAIN)
261  {
262  vPos = GenerateRandomPosition(soundGroup, camPos);
263  soundType = GetTerrainTypeFromTerrain(vPos);
264  }
265  else if (spawhMethod == ESpawnMethod.SOUNDMAP)
266  {
267  vPos = GenerateRandomPosition(soundGroup, camPos);
268  soundType = GetSoundMapTypeFromTerrain(vPos);
269  }
270 
271  if (soundType == INVALID)
272  return;
273 
274  // Get random sound definition
275  int soundDef = GetRandomSoundDef(m_aSoundGroup[soundGroup].m_aSoundType[soundType], worldTime);
276 
277  if (soundDef == INVALID)
278  return;
279 
280  // Create sound event sequence
281  vector mat[4];
282  Math3D.MatrixIdentity4(mat);
283  mat[3] = vPos;
284 
285  SCR_SoundHandle soundHandle = new SCR_SoundHandle(soundGroup, soundType, soundDef, mat, m_aSoundGroup, worldTime);
286  m_aSoundHandle.Insert(soundHandle);
287 
288  // Set CoolDownEnd time
289  float timeOfDayFactor = m_aDayTimeCurveValue[soundHandle.m_SoundDef.m_eDayTimeCurve];
290  timeOfDayFactor = (1 - Math.Clamp(timeOfDayFactor, 0, 1));
291  timeOfDayFactor = Math.Pow(timeOfDayFactor, 3) * 4 + 1;
292 
293  if (soundHandle.m_SoundDef.m_bAddSequenceLength)
294  soundHandle.m_SoundDef.m_fCoolDownEnd = worldTime + soundHandle.GetSequenceLenght(worldTime) + soundHandle.m_SoundDef.m_iCoolDown * timeOfDayFactor;
295  else
296  soundHandle.m_SoundDef.m_fCoolDownEnd = worldTime + soundHandle.m_SoundDef.m_iCoolDown * timeOfDayFactor;
297  }
298 
299  //------------------------------------------------------------------------------------------------
300  private vector GenerateRandomPosition(int soundGroup, vector camPos)
301  {
302  // Angle for random position is rotated by 36 deg for each GenerateRandomPosition() call
303  float angle = m_aAngleOffset[soundGroup] * 36;
304 
305  m_aAngleOffset[soundGroup] = m_aAngleOffset[soundGroup] + 1;
306  if (m_aAngleOffset[soundGroup] > 9)
307  m_aAngleOffset[soundGroup] = 0;
308 
309  float fDist = m_aSpawnDef[soundGroup].m_iSpawnDist;
310  vector vPos = vector.FromYaw(angle) * fDist;
311 
312  return vPos + camPos;
313  }
314 
315  //------------------------------------------------------------------------------------------------
316  private int GetRandomSoundDef(SCR_SoundType soundType, float worldTime)
317  {
318  int size = soundType.m_aSoundDef.Count();
319  if (size == 0)
320  return INVALID;
321 
322  int offset = Math.RandomIntInclusive(0, size - 1);
323 
324  for (int i = 0; i < size; i++)
325  {
326  int idx = i + offset;
327  if (idx >= size)
328  idx -= size;
329 
330  if (m_aDayTimeCurveValue[soundType.m_aSoundDef[idx].m_eDayTimeCurve] > 0 && soundType.m_aSoundDef[idx].m_fCoolDownEnd < worldTime)
331  return idx;
332  }
333 
334  return INVALID;
335  }
336 
337  //------------------------------------------------------------------------------------------------
338  private ETerrainType GetTerrainType(int soundInfo)
339  {
340  foreach(SCR_TerrainDef terrainDef : m_aTerrainDef)
341  {
342  if (soundInfo >= terrainDef.m_iRangeMin && soundInfo < terrainDef.m_iRangeMax)
343  return terrainDef.m_eTerrainType;
344  }
345 
346  return INVALID;
347  }
348 
349  //------------------------------------------------------------------------------------------------
350  private ESoundMapType GetSoundMapTypeFromTerrain(inout vector worldPos)
351  {
352  // Check for fresh water
353  float surfaceHeight = m_World.GetSurfaceY(worldPos[0], worldPos[2]);
354  worldPos[1] = surfaceHeight;
355 
356  EWaterSurfaceType waterSurfaceType;
357  float lakeArea;
358  float waterSurfaceY = GetWaterSurfaceY(worldPos, waterSurfaceType, lakeArea);
359 
360  switch (waterSurfaceType)
361  {
362  case EWaterSurfaceType.WST_NONE:
363  {
364  m_SoundWorld = m_World.GetSoundWorld();
365 
366  if(!m_SoundWorld)
367  return INVALID;
368 
369  float sea, forest, city, meadow;
370  m_SoundWorld.GetMapValuesAtPos(worldPos, sea, forest, city, meadow);
371 
372  // Get maximum
373  float vals[] = { meadow, forest, city, sea };
374  float v = vals[0];
375  int idx;
376  for (int i = 1; i < 4; i++)
377  {
378  if (vals[i] > v)
379  {
380  v = vals[i];
381  idx = i;
382  }
383  }
384 
385  return idx;
386  }
387  case EWaterSurfaceType.WST_OCEAN:
388  {
389  worldPos[1] = 0;
390  return ESoundMapType.SEA;
391  }
392  case EWaterSurfaceType.WST_POND:
393  {
394  if (lakeArea > LAKE_AREA_LIMIT)
395  {
396  worldPos[1] = waterSurfaceY;
397  return ESoundMapType.POND;
398  }
399  else
400  return INVALID;
401  }
402  }
403 
404  return INVALID;
405  }
406 
407  //------------------------------------------------------------------------------------------------
408  private ETerrainType GetTerrainTypeFromTerrain(inout vector worldPos)
409  {
410  // Get surface height
411  float surfaceHeight = m_World.GetSurfaceY(worldPos[0], worldPos[2]);
412  worldPos[1] = surfaceHeight;
413 
414  // Ignore when near sea coast
415  if (Math.AbsFloat(worldPos[1]) < COAST_HIGHT_LIMIT)
416  return INVALID;
417 
418  EWaterSurfaceType waterSurfaceType;
419  float lakeArea;
420  float waterSurfaceY = GetWaterSurfaceY(worldPos, waterSurfaceType, lakeArea);
421 
422  switch (waterSurfaceType)
423  {
424  case EWaterSurfaceType.WST_NONE:
425  {
426  // Trace and get soundInfo
427  int soundInfo = INVALID;
428  m_AmbientSoundsComponent.TracePointToTerrain(worldPos, soundInfo);
429 
430  // Get soundGroup
431  return GetTerrainType(soundInfo);
432  }
433  case EWaterSurfaceType.WST_OCEAN:
434  {
435  worldPos[1] = 0;
436  return ETerrainType.OCEAN;
437  }
438  case EWaterSurfaceType.WST_POND:
439  {
440  if (lakeArea > LAKE_AREA_LIMIT)
441  {
442  worldPos[1] = waterSurfaceY;
443  return ETerrainType.POND;
444  }
445  else
446  return ETerrainType.POND_SMALL;
447  }
448  }
449 
450  return INVALID;
451  }
452 
453  //------------------------------------------------------------------------------------------------
454  private float GetWaterSurfaceY(vector worldPos, out EWaterSurfaceType waterSurfaceType, out float lakeArea)
455  {
456  vector waterSurfacePos;
457  vector transformWS[4];
458  vector obbExtents;
459 
460  ChimeraWorldUtils.TryGetWaterSurface(m_World, worldPos, waterSurfacePos, waterSurfaceType, transformWS, obbExtents);
461  lakeArea = obbExtents[0] * obbExtents[2];
462 
463  return waterSurfacePos[1];
464  }
465 
466  //------------------------------------------------------------------------------------------------
467  private vector GetRandomPositionOnEntity(IEntity entity)
468  {
469  vector mins, maxs;
470  entity.GetWorldBounds(mins, maxs);
471 
472  vector pos;
473 
474  // Get position
475  pos = entity.GetOrigin();
476 
477  // Set random height
478  pos[1] = pos[1] + (maxs[1] - mins[1]) * Math.RandomFloatInclusive(0.5, 1);
479 
480  return pos;
481  }
482 
483  //------------------------------------------------------------------------------------------------
484  private void UpdateDensity()
485  {
486  foreach (SCR_SoundHandle soundHandle : m_aSoundHandle)
487  {
488  m_aDensity[soundHandle.m_iSoundGroup] = m_aDensity[soundHandle.m_iSoundGroup] + soundHandle.m_fDensity;
489  }
490 
491  for (int i = 0, count = m_aSpawnDef.Count(); i < count; i++)
492  {
493  m_aDensity[i] = m_aDensity[i] * 0.5;
494  }
495  }
496 
497  //------------------------------------------------------------------------------------------------
498  private float Interpolate01(float in, float Xmin, float Xmax)
499  {
500  if (in <= Xmin)
501  return 0;
502 
503  if (in >= Xmax)
504  return 1;
505 
506  return (in - Xmin) / (Xmax - Xmin);
507  }
508 
509  //------------------------------------------------------------------------------------------------
510  private void UpdateSignlsIdx()
511  {
512  m_iSunAngleSignalIdx = m_LocalSignalsManager.AddOrFindSignal(SUN_ANGLE_SIGNAL_NAME);
513  m_iSoundNameSignalIdx = m_LocalSignalsManager.AddOrFindSignal(SOUND_NAME_SIGNAL_NAME);
515  m_iEnvironmentTypeSignalIdx = m_LocalSignalsManager.AddOrFindSignal(ENVIRONMENT_TYPE_SIGNAL_NAME);
516 
517  m_iRainIntensitySignalIdx = m_GlobalSignalsManager.AddOrFindSignal(RAIN_INTENSITY_SIGNAL_NAME);
518  m_iWindSpeedSignalIdx = m_GlobalSignalsManager.AddOrFindSignal(WIND_SPEED_SIGNAL_NAME);
519  }
520 
521  //------------------------------------------------------------------------------------------------
522  private void LoadConfigs(SCR_AmbientSoundsComponent ambientSoundsComponent)
523  {
524  foreach (SCR_RandomPositionalSoundsDef def: m_aRandomPositionalSoundsDef)
525  {
526  SCR_SoundGroup soundGrop;
527  if (def.m_SoundGroupResource != string.Empty)
528  {
529  Resource holder = BaseContainerTools.LoadContainer(def.m_SoundGroupResource);
530  if (holder)
531  soundGrop = SCR_SoundGroup.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
532  }
533 
534  if (!soundGrop)
535  {
536  ambientSoundsComponent.SetScriptedMethodsCall(false);
537  Print("AUDIO: SCR_AmbientSoundsComponent: Missing Ambience Sound Gropu Config", LogLevel.WARNING);
538  return;
539  }
540 
541  m_aSoundGroup.Insert(soundGrop);
542 
543  // ---
544  SCR_SpawnDef spawnDef;
545  if (def.m_SpawnDefResource != string.Empty)
546  {
547  Resource holder = BaseContainerTools.LoadContainer(def.m_SpawnDefResource);
548  if (holder)
549  spawnDef = SCR_SpawnDef.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
550  }
551 
552  if (!spawnDef)
553  {
554  ambientSoundsComponent.SetScriptedMethodsCall(false);
555  Print("AUDIO: SCR_AmbientSoundsComponent: Missing Spawn Definition Config", LogLevel.WARNING);
556  return;
557  }
558 
559  m_aSpawnDef.Insert(spawnDef);
560  }
561 
562  // ---
563  SCR_TerrainDefConfig soundTerrainDefinitionConfig;
564  if (m_TerrainDefinitionResource != string.Empty)
565  {
566  Resource holder = BaseContainerTools.LoadContainer(m_TerrainDefinitionResource);
567  if (holder)
568  soundTerrainDefinitionConfig = SCR_TerrainDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
569  }
570 
571  if (!soundTerrainDefinitionConfig)
572  {
573  ambientSoundsComponent.SetScriptedMethodsCall(false);
574  Print("AUDIO: SCR_AmbientSoundsComponent: Missing Sound Definition Terrain Config", LogLevel.WARNING);
575  return;
576  }
577 
578  m_aTerrainDef = soundTerrainDefinitionConfig.m_aTerrainDef;
579 
580  // ---
581  SCR_DayTimeCurveDefConfig ambientSoundsDayTimeCurveDefinitionConfig;
582  if (m_DayTimeCurveResource != string.Empty)
583  {
584  Resource holder = BaseContainerTools.LoadContainer(m_DayTimeCurveResource);
585  if (holder)
586  ambientSoundsDayTimeCurveDefinitionConfig = SCR_DayTimeCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
587  }
588 
589  if (!ambientSoundsDayTimeCurveDefinitionConfig)
590  {
591  ambientSoundsComponent.SetScriptedMethodsCall(false);
592  Print("AUDIO: SCR_AmbientSoundsComponent: Missing Daytime Curve Deffinition Config", LogLevel.WARNING);
593  return;
594  }
595 
596  m_aDayTimeCurve = ambientSoundsDayTimeCurveDefinitionConfig.m_aDayTimeCurve;
597 
598  // ---
599  SCR_WindCurveDefConfig ambientSoundsWindDefinitionConfig;
600  if (m_WindCurveResource != string.Empty)
601  {
602  Resource holder = BaseContainerTools.LoadContainer(m_WindCurveResource);
603  if (holder)
604  ambientSoundsWindDefinitionConfig = SCR_WindCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
605  }
606 
607  if (!ambientSoundsWindDefinitionConfig)
608  {
609  ambientSoundsComponent.SetScriptedMethodsCall(false);
610  Print("AUDIO: SCR_AmbientSoundsComponent: Missing Wind Curve Definition Config", LogLevel.WARNING);
611  return;
612  }
613 
614  m_aWindModifier = ambientSoundsWindDefinitionConfig.m_aWindModifier;
615  }
616 
617  //------------------------------------------------------------------------------------------------
618 #ifdef ENABLE_DIAG
619  private const int STRING_LENGTH = 25;
620  private const int PANEL_WIDTH = 20;
621  private const int PANEL_HEIGHT = 20;
622 
623  //------------------------------------------------------------------------------------------------
625  void AmbientSignalsDebug()
626  {
627  DbgUI.Begin("Ambient Sounds Signals", 178, 0);
628  DbgUI.Text(SUN_ANGLE_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iSunAngleSignalIdx).ToString());
629  DbgUI.Text(SOUND_NAME_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iSoundNameSignalIdx).ToString());
630  DbgUI.Text(DISTANCE_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iDistanceSignalIdx).ToString());
631  DbgUI.Text("Environent Type : " + typename.EnumToString(EEnvironmentType, m_iEnvironmentTypeSignalValue));
632  DbgUI.End();
633  }
634 
635  //------------------------------------------------------------------------------------------------
637  void DensityDebug()
638  {
639  DbgUI.Begin("Density", 420, 0);
640  for (int i = 0, count = m_aSpawnDef.Count(); i < count; i++)
641  {
642  DbgUI.Text(m_aSoundGroup[i].m_sSoundEvent + ": " + m_aDensity[i].ToString() + " / " + (Math.Round(GetDensityMax(i) * m_aDensityModifier[i])).ToString());
643  }
644  DbgUI.End();
645  }
646 
647  //------------------------------------------------------------------------------------------------
650  void RandomPositionalSoundDebug(float worldTime)
651  {
652  int defaultColor = ARGB(255, 50, 50, 50);
653  int blackColor = ARGB(255, 0, 0, 0);
654  int availableColor = ARGB(255, 0, 0, 255);
655  int playingColor = ARGB(255, 255, 255, 0);
656  int wrongTimeColor = ARGB(255, 125, 125, 125);
657  int inCooldownColor = ARGB(255, 255, 0, 255);
658 
659  DbgUI.Begin("Random Ambient Sounds", 0, 185);
660 
661  DbgUI.Panel("av", PANEL_WIDTH, PANEL_HEIGHT, availableColor);
662  DbgUI.SameLine();
663  DbgUI.Text("Available");
664  DbgUI.SameLine();
665  DbgUI.Panel("pl", PANEL_WIDTH, PANEL_HEIGHT, playingColor);
666  DbgUI.SameLine();
667  DbgUI.Text("Playing");
668  DbgUI.SameLine();
669  DbgUI.Panel("wt", PANEL_WIDTH, PANEL_HEIGHT, wrongTimeColor);
670  DbgUI.SameLine();
671  DbgUI.Text("WrongTime");
672  DbgUI.SameLine();
673  DbgUI.Panel("in", PANEL_WIDTH, PANEL_HEIGHT, inCooldownColor);
674  DbgUI.SameLine();
675  DbgUI.Text("InCooldown");
676 
677  for (int soundGroup = 0; soundGroup < m_aSpawnDef.Count(); soundGroup++)
678  {
679  // Get SoundGropu name
680  string name = m_aSoundGroup[soundGroup].m_sSoundEvent;
681  name = NormalizeLength(name);
682  name = soundGroup.ToString() + ". " + name;
683 
684  // Show number of playing sounds
685  int limitCount = 8;
686  int playingCount = 0;
687 
688  bool bSoundTypeChecked = false;
689  DbgUI.Check(name, bSoundTypeChecked);
690 
691  for (int i = 0; i < m_aSoundHandle.Count(); i++)
692  {
693  if (m_aSoundHandle[i].m_iSoundGroup == soundGroup)
694  playingCount ++;
695  }
696 
697  for (int i = 0; i < limitCount; i++)
698  {
699  int color = defaultColor;
700 
701  if (i < playingCount)
702  {
703  color = playingColor;
704  }
705 
706  DbgUI.SameLine();
707  DbgUI.Panel(soundGroup.ToString() + "." + i.ToString(), PANEL_WIDTH, PANEL_HEIGHT, color);
708  }
709 
710  if (bSoundTypeChecked)
711  {
712  int soundTypeCount = m_aSoundGroup[soundGroup].m_aSoundType.Count();
713 
714  for (int soundType = 0; soundType < soundTypeCount; soundType++)
715  {
716  // Get SoundType name
717  string soundTypeName;
718  if (m_aSoundGroup[soundGroup].m_eSpawnMethod == ESpawnMethod.ENTITY)
719  {
720  if (soundType == 0)
721  soundTypeName = "CONIFER";
722  else
723  soundTypeName = "LEAFY";
724  }
725  else if (m_aSoundGroup[soundGroup].m_eSpawnMethod == ESpawnMethod.TERRAIN)
726  soundTypeName = typename.EnumToString(ETerrainType, soundType);
727  else
728  soundTypeName = typename.EnumToString(ESoundMapType, soundType);
729 
730  soundTypeName = NormalizeLength(soundTypeName);
731 
732  DbgUI.Panel(soundGroup.ToString() + soundType.ToString(), PANEL_WIDTH, PANEL_HEIGHT, blackColor);
733  DbgUI.SameLine();
734  bool bSoundGroupChecked = false;
735  DbgUI.Check(soundGroup.ToString() + "." + soundType.ToString() + ". " + soundTypeName, bSoundGroupChecked);
736  DbgUI.SameLine();
737 
738  int size = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count();
739  int available = 0;
740  for (int idx = 0; idx < size; idx++)
741  {
742  if (m_aDayTimeCurveValue[m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[idx].m_eDayTimeCurve] > 0 && m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[idx].m_fCoolDownEnd < worldTime)
743  available++;
744  }
745 
746  DbgUI.Text(soundGroup.ToString() + "." + soundType.ToString() + ". " + "Available :" + available.ToString() + " of (" + m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count() + ")");
747 
748  if (bSoundGroupChecked)
749  {
750  int soundDefCount = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count();
751 
752  for (int soundDef = 0; soundDef < soundDefCount; soundDef++)
753  {
754  int color = defaultColor;
755  string aditionalInfo = "";
756 
757  // -----------------------
758  // -----Status panel------
759  // -----------------------
760 
761  // Tag if sound is in cooldown
762  if (m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd > worldTime)
763  {
764  color = inCooldownColor;
765  aditionalInfo = " | Coldown ends in : " + Math.Round((m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd - worldTime) * 0.001).ToString();
766 
767  float timeOfDayFactor = m_aDayTimeCurveValue[m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eDayTimeCurve];
768  timeOfDayFactor = (1 - Math.Clamp(timeOfDayFactor, 0, 1));
769  timeOfDayFactor = Math.Pow(timeOfDayFactor, 3) * 4 + 1;
770  timeOfDayFactor = Math.Round(timeOfDayFactor * 100) * 0.01;
771 
772  aditionalInfo = aditionalInfo + " | TFactor : " + timeOfDayFactor.ToString();
773  }
774 
775  // Tag sounds that can not play in given time of day
776  if (m_aDayTimeCurveValue[m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eDayTimeCurve] <= 0)
777  color = wrongTimeColor;
778 
779  // Tag available
780  if (m_aDayTimeCurveValue[m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eDayTimeCurve] > 0 && m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd <= worldTime)
781  color = availableColor;
782 
783  DbgUI.Panel(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString(), PANEL_WIDTH * 2 + 5, PANEL_HEIGHT, color);
784 
785  // -----------------------
786  // -Sound definition name-
787  // -----------------------
788 
789  string soundDefinitionName = typename.EnumToString(ESoundName, m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eSoundName);
790  soundDefinitionName = NormalizeLength(soundDefinitionName);
791  DbgUI.SameLine();
792  DbgUI.Text(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString() + ". " + soundDefinitionName + " ");
793 
794  // -----------------------
795  // - Number of instances -
796  // -----------------------
797 
798  int instanceCount = 0;
799  float playbackEnd = 0;
800 
801  foreach (SCR_SoundHandle sh: m_aSoundHandle)
802  {
803  if (sh.m_iSoundGroup == soundGroup && sh.m_iSoundType == soundType && sh.m_iSoundDef == soundDef)
804  {
805  instanceCount ++;
806 
807  if (playbackEnd < Math.Round(sh.m_aRepTime[sh.m_aRepTime.Count() - 1] - worldTime))
808  {
809  playbackEnd = Math.Round(sh.m_aRepTime[sh.m_aRepTime.Count() - 1] - worldTime);
810  }
811  }
812  }
813 
814  playbackEnd = Math.Round(playbackEnd * 0.001);
815 
816  if (playbackEnd > 0)
817  {
818  aditionalInfo = aditionalInfo + " | Playback ends in : " + playbackEnd.ToString();
819  }
820 
821  for (int j = 0; j < instanceCount; j++)
822  {
823  DbgUI.SameLine();
824  DbgUI.Panel(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString() + "Play" + j.ToString(), PANEL_WIDTH, PANEL_HEIGHT, playingColor);
825  }
826 
827  // -----------------------
828  // -----Aditional info----
829  // -----------------------
830 
831  DbgUI.SameLine();
832  DbgUI.Text(aditionalInfo);
833  }
834  }
835  }
836  }
837  }
838 
839  DbgUI.End();
840  }
841 
842  //------------------------------------------------------------------------------------------------
843  private string NormalizeLength(string name)
844  {
845  int length = name.Length();
846  string s = name;
847 
848  if (length <= STRING_LENGTH)
849  {
850  for (int i = 0; i < (STRING_LENGTH - length); i++)
851  {
852  s = s + " ";
853  }
854  }
855  else
856  s = s.Substring(0, STRING_LENGTH * 0.5 - 2) + "...." + s.Substring(length - STRING_LENGTH * 0.5, STRING_LENGTH * 0.5);
857 
858  return s;
859  }
860 
861  //------------------------------------------------------------------------------------------------
862  override void ReloadConfig()
863  {
864  super.ReloadConfig();
865 
866  m_aSoundGroup.Clear();
867  m_aSpawnDef.Clear();
868 
869  foreach (SCR_RandomPositionalSoundsDef def: m_aRandomPositionalSoundsDef)
870  {
871  SCR_SoundGroup soundGrop;
872  if (def.m_SoundGroupResource != string.Empty)
873  {
874  Resource holder = BaseContainerTools.LoadContainer(def.m_SoundGroupResource);
875  if (holder)
876  soundGrop = SCR_SoundGroup.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
877  }
878 
879  if (soundGrop)
880  m_aSoundGroup.Insert(soundGrop);
881 
882  // ---
883  SCR_SpawnDef spawnDef;
884  if (def.m_SpawnDefResource != string.Empty)
885  {
886  Resource holder = BaseContainerTools.LoadContainer(def.m_SpawnDefResource);
887  if (holder)
888  spawnDef = SCR_SpawnDef.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
889  }
890 
891  if (spawnDef)
892  m_aSpawnDef.Insert(spawnDef);
893  }
894 
895  // ---
896  SCR_TerrainDefConfig soundTerrainDefinitionConfig;
897  if (m_TerrainDefinitionResource != string.Empty)
898  {
899  Resource holder = BaseContainerTools.LoadContainer(m_TerrainDefinitionResource);
900  if (holder)
901  soundTerrainDefinitionConfig = SCR_TerrainDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
902  }
903 
904  if (soundTerrainDefinitionConfig)
905  m_aTerrainDef = soundTerrainDefinitionConfig.m_aTerrainDef;
906 
907  // ---
908  SCR_DayTimeCurveDefConfig ambientSoundsDayTimeCurveDefinitionConfig;
909  if (m_DayTimeCurveResource != string.Empty)
910  {
911  Resource holder = BaseContainerTools.LoadContainer(m_DayTimeCurveResource);
912  if (holder)
913  ambientSoundsDayTimeCurveDefinitionConfig = SCR_DayTimeCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
914  }
915 
916  if (!ambientSoundsDayTimeCurveDefinitionConfig)
917  m_aDayTimeCurve = ambientSoundsDayTimeCurveDefinitionConfig.m_aDayTimeCurve;
918 
919  // ---
920  SCR_WindCurveDefConfig ambientSoundsWindDefinitionConfig;
921  if (m_WindCurveResource != string.Empty)
922  {
923  Resource holder = BaseContainerTools.LoadContainer(m_WindCurveResource);
924  if (holder)
925  ambientSoundsWindDefinitionConfig = SCR_WindCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
926  }
927 
928  if (ambientSoundsWindDefinitionConfig)
929  m_aWindModifier = ambientSoundsWindDefinitionConfig.m_aWindModifier;
930 
931  m_aSoundHandle.Clear();
932  }
933 
934  //------------------------------------------------------------------------------------------------
935  private void PlaySound(float worldTime)
936  {
937  DbgUI.Begin("Play Sound", 0, 0);
938 
939  int soundGroup = 3;
940  int soundType = 2;
941  int soundDef = 0;
942  float distanceFactor = 0.15;
943  DbgUI.InputInt("Sound Group:", soundGroup, 50);
944  DbgUI.InputInt("Sound Type :", soundType, 50);
945  DbgUI.InputInt("Sound Def :", soundDef, 50);
946  DbgUI.InputFloat("Dist Factor:", distanceFactor, 50);
947 
948  bool play = DbgUI.Button("Play");
949  DbgUI.SameLine();
950  bool clear = DbgUI.Button("Clear");
951 
952  if (play)
953  {
954  // Check if sound definition is correct
955  if (soundGroup >= m_aSoundGroup.Count() || soundType >= m_aSoundGroup[soundGroup].m_aSoundType.Count() || soundDef >= m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count())
956  return;
957 
958  // Get camera transf
959  vector mat[4];
960  GetGame().GetCameraManager().CurrentCamera().GetTransform(mat);
961 
962  // Get direction
963  vector yaw = mat[0];
964  float angle = yaw.ToYaw();
965  angle -= 90;
966  yaw = vector.FromYaw(angle);
967 
968  // Get sound position
969  float dist = Math.Lerp(m_aSpawnDef[soundGroup].m_iPlayDistMin, m_aSpawnDef[soundGroup].m_iPlayDistMax, distanceFactor);
970  mat[3] = mat[3] + yaw * dist;
971 
972  // Add sound to pool
973  SCR_SoundHandle soundHandle = new SCR_SoundHandle(soundGroup, soundType, soundDef, mat, m_aSoundGroup, worldTime);
974  m_aSoundHandle.Insert(soundHandle);
975  }
976 
977  if (clear)
978  m_aSoundHandle.Clear();
979 
980  DbgUI.End();
981  }
982 
983 #endif
984 
985  //------------------------------------------------------------------------------------------------
986  override void OnPostInit(SCR_AmbientSoundsComponent ambientSoundsComponent, SignalsManagerComponent signalsManagerComponent)
987  {
988  super.OnPostInit(ambientSoundsComponent, signalsManagerComponent);
989 
990  LoadConfigs(ambientSoundsComponent);
991 
992  m_LocalSignalsManager = signalsManagerComponent;
993  m_GlobalSignalsManager = GetGame().GetSignalsManager();
994  m_AmbientSoundsComponent = ambientSoundsComponent;
995 
996  int count = m_aSpawnDef.Count();
997  m_aDensity.Resize(count);
998  m_aAngleOffset.Resize(count);
999  m_aDensityModifier.Resize(count);
1000 
1001  UpdateSignlsIdx();
1002  m_World = ChimeraWorld.CastFrom(GetGame().GetWorld());
1003 
1004 #ifdef ENABLE_DIAG
1005  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS, "", "Random Ambient Sounds", "Sounds");
1006 #endif
1007  }
1008 
1009  //------------------------------------------------------------------------------------------------
1010  override void OnInit()
1011  {
1012  super.OnInit();
1013 
1014  UpdateGlobalModifiers();
1015  }
1016 
1017  //------------------------------------------------------------------------------------------------
1018  // destructor
1019  void ~SCR_RandomPositionalSounds()
1020  {
1021 #ifdef ENABLE_DIAG
1022  if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS))
1023  {
1024  foreach (SCR_SoundGroup soundGroup : m_aSoundGroup)
1025  {
1026  foreach (SCR_SoundType soundType : soundGroup.m_aSoundType)
1027  {
1028  foreach (SCR_SoundDef soundDef : soundType.m_aSoundDef)
1029  {
1030  Print(typename.EnumToString(ESoundName, soundDef.m_eSoundName) + ": " + soundDef.m_iCount, LogLevel.NORMAL);
1031  }
1032  }
1033  }
1034  }
1035 
1036  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS);
1037 #endif
1038  }
1039 }
POND
POND
Definition: SCR_RandomPositionalSounds.c:6
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_TerrainDefConfig
Array has to have the same size as ESoundType count.
Definition: SCR_TerrainDefConfig.c:3
PlaySound
SCR_ParticleContactComponentClass ScriptComponentClass PlaySound(IEntity owner, SCR_ParticleContactComponentClass prefabData, Contact contact)
Definition: SCR_ParticleContactComponent.c:38
EQueryType
EQueryType
Definition: SCR_AmbientSoundsComponent.c:1
MEADOW
MEADOW
Definition: SCR_RandomPositionalSounds.c:2
m_iDistanceSignalIdx
protected int m_iDistanceSignalIdx
Definition: SCR_HelicopterSoundComponent.c:24
WIND_CURVE_COUNT
const int WIND_CURVE_COUNT
Definition: SCR_WindCurveDef.c:2
SCR_SoundType
Definition: SCR_SoundType.c:2
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
ETerrainType
ETerrainType
Definition: SCR_TerrainDef.c:1
m_AmbientSoundsComponent
protected SCR_AmbientSoundsComponent m_AmbientSoundsComponent
Definition: SCR_PositionalInsectType.c:14
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
ESoundMapType
ESoundMapType
Definition: SCR_RandomPositionalSounds.c:1
SCR_DayTimeCurveDefConfig
Array size has to have the same count as EDayTimeCurve.
Definition: SCR_DayTimeCurveDefConfig.c:3
EEnvironmentType
EEnvironmentType
Definition: SCR_SpawnDef.c:1
Attribute
typedef Attribute
Post-process effect of scripted camera.
INVALID
@ INVALID
Missing components, or obstruction test was not possible.
Definition: SCR_CharacterRankComponent.c:326
m_LocalSignalsManager
protected SignalsManagerComponent m_LocalSignalsManager
Definition: SCR_PositionalInsectType.c:15
Update
override void Update(float timeSlice)
Definition: SCR_CampaignBuildingGadgetToolComponent.c:28
ESoundName
ESoundName
Definition: SCR_SoundDef.c:1
OnPostInit
override void OnPostInit(IEntity owner)
Called on PostInit when all components are added.
Definition: SCR_AIConfigComponent.c:72
DAY_TIME_CURVE_COUNT
const int DAY_TIME_CURVE_COUNT
Definition: SCR_DayTimeCurveDef.c:1
SCR_AmbientSoundsComponent
Definition: SCR_AmbientSoundsComponent.c:17
m_World
protected BaseWorld m_World
Definition: SCR_PreviewEntityEditorUIComponent.c:46
SCR_SoundHandle
Definition: SCR_SoundHandle.c:2
SCR_RandomPositionalSoundsDef
Definition: SCR_RandomPositionalSoundsDef.c:2
HOUSES
HOUSES
Definition: SCR_RandomPositionalSounds.c:4
FOREST
FOREST
Definition: SCR_RandomPositionalSounds.c:3
DISTANCE_SIGNAL_NAME
const protected string DISTANCE_SIGNAL_NAME
Definition: SCR_HelicopterSoundComponent.c:10
UpdateDebug
protected void UpdateDebug()
Definition: SCR_AISettingsComponent.c:79
ESpawnMethod
ESpawnMethod
Definition: SCR_SoundGroup.c:1
BaseContainerProps
enum ESoundMapType BaseContainerProps(configRoot:true)
Definition: SCR_RandomPositionalSounds.c:15
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SEA
SEA
Definition: SCR_RandomPositionalSounds.c:5
GameSignalsManager
Definition: GameSignalsManager.c:7
OnInit
override protected void OnInit(IEntity owner)
Definition: SCR_CharacterCommandHandler_Tests.c:523
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
SCR_WindCurveDefConfig
Array has to have the same size as EWindCurve count.
Definition: SCR_WindCurveDefConfig.c:3
ChimeraWorldUtils
Definition: ChimeraWorldUtils.c:7
EWaterSurfaceType
EWaterSurfaceType
Definition: EWaterSurfaceType.c:7
SCR_AmbientSoundsEffect
Definition: SCR_AmbientSoundsEffect.c:2