Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_RandomPositionalSounds.c
Go to the documentation of this file.
2{
3 MEADOW,
4 FOREST,
5 HOUSES,
6 SEA,
7 POND,
8}
9
15[BaseContainerProps(configRoot: true)]
16class SCR_RandomPositionalSounds : SCR_AmbientSoundsEffect
19 private ref array<ref SCR_RandomPositionalSoundsDef> m_aRandomPositionalSoundsDef;
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 GLOBAL_MODIFIERS_UPDATE_TIME = 10000;
45 private const string SUN_ANGLE_SIGNAL_NAME = "SunAngle";
46 private const string SOUND_NAME_SIGNAL_NAME = "SoundName";
47 private const string DISTANCE_SIGNAL_NAME = "Distance";
48 private const string RAIN_INTENSITY_SIGNAL_NAME = "RainIntensity";
49 private const string WIND_SPEED_SIGNAL_NAME = "WindSpeed";
50 private const string ENVIRONMENT_TYPE_SIGNAL_NAME = "EnvironmentType";
51
52 // Signal Idxs
53 private int m_iSunAngleSignalIdx;
54 private int m_iSoundNameSignalIdx;
55 private int m_iDistanceSignalIdx;
56 private int m_iRainIntensitySignalIdx;
57 private int m_iWindSpeedSignalIdx;
58 private int m_iEnvironmentTypeSignalIdx;
59
60 private int m_iUpdatedSoundGroupIdx;
61 private float m_fGlobalModifiersTimer;
62 private ref array<int> m_aDensity = {};
63 private ref array<float> m_aDensityModifier = {};
64 private ref array<int> m_aAngleOffset = {};
65 private float m_aDayTimeCurveValue[DAY_TIME_CURVE_COUNT];
66 private float m_aWindCurveValue[WIND_CURVE_COUNT];
67
68 private ref array<ref SCR_SoundHandle> m_aSoundHandle = {};
69
70 //------------------------------------------------------------------------------------------------
71 ChimeraWorld GetWorld()
72 {
73 return m_World;
74 }
75
76 //------------------------------------------------------------------------------------------------
77 ETerrainType GetTerrainType(int soundInfo)
78 {
79 foreach(SCR_TerrainDef terrainDef : m_aTerrainDef)
80 {
81 if (soundInfo >= terrainDef.m_iRangeMin && soundInfo < terrainDef.m_iRangeMax)
82 return terrainDef.m_eTerrainType;
83 }
84
85 return INVALID;
86 }
87
88 //------------------------------------------------------------------------------------------------
89 // Called by SCR_AmbientSoundComponent in UpdateSoundJob()
90 override void Update(float worldTime, vector cameraPos, bool forceUpdate)
91 {
92 ProcessSoundGroups(worldTime, cameraPos);
93 UpdateSoundSequence(worldTime, cameraPos);
94
95 if (worldTime > m_fGlobalModifiersTimer)
96 {
97 UpdateGlobalModifiers();
98 RemoveSoundsBasedOnTimeAndWeather();
99 m_fGlobalModifiersTimer = worldTime + GLOBAL_MODIFIERS_UPDATE_TIME;
100 }
101 }
102
103#ifdef ENABLE_DIAG
104 //------------------------------------------------------------------------------------------------
105 override void UpdateDebug(float worldTime)
106 {
107 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS))
108 {
109 AmbientSignalsDebug();
110 RandomPositionalSoundDebug(worldTime);
111 DensityDebug();
112 PlaySound(worldTime);
113 }
114 }
115#endif
116
117 //------------------------------------------------------------------------------------------------
118 private void ProcessSoundGroups(float worldTime, vector cameraPos)
119 {
120 UpdateSoundGroup(worldTime, cameraPos, m_iUpdatedSoundGroupIdx);
121
122 m_iUpdatedSoundGroupIdx ++;
123 if (m_iUpdatedSoundGroupIdx < m_aSoundGroup.Count())
124 return;
125
126 m_iUpdatedSoundGroupIdx = 0;
127
128 RemoveOutOfRangeSound(cameraPos);
129 UpdateDensity();
130 }
131
132 //------------------------------------------------------------------------------------------------
134 private void RemoveSoundsBasedOnTimeAndWeather()
135 {
136 for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
137 {
138 SCR_SoundHandle soundHandle = m_aSoundHandle[i];
139
140 if (m_aDayTimeCurveValue[soundHandle.m_SoundDef.m_eDayTimeCurve] == 0 || m_aDensityModifier[soundHandle.m_iSoundGroup] == 0)
141 m_aSoundHandle.Remove(i);
142 }
143 }
144
145 //------------------------------------------------------------------------------------------------
147 private void UpdateGlobalModifiers()
148 {
149 //Update values of wind modifiers curves
150 float windSpeedScaled = Interpolate01(m_GlobalSignalsManager.GetSignalValue(m_iWindSpeedSignalIdx), SCR_AmbientSoundsComponent.WINDSPEED_MIN, SCR_AmbientSoundsComponent.WINDSPEED_MAX);
151 for (int i = 0; i < WIND_CURVE_COUNT; i++)
152 {
153 m_aWindCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(windSpeedScaled, m_aWindModifier[i].m_Curve);
154 }
155
156 float timeOfDay = m_LocalSignalsManager.GetSignalValue(m_iSunAngleSignalIdx) / 360;
157
158 foreach (int i, SCR_SpawnDef spawnDef : m_aSpawnDef)
159 {
160 float modifier = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, spawnDef.m_TimeModifier);
161 modifier = modifier * SCR_AmbientSoundsComponent.GetPoint(m_GlobalSignalsManager.GetSignalValue(m_iRainIntensitySignalIdx), spawnDef.m_RainModifier);
162 m_aDensityModifier[i] = modifier * m_aWindCurveValue[spawnDef.m_eWindModifier];
163 }
164
165 // Update values of day time curves
166 for (int i = 0; i < DAY_TIME_CURVE_COUNT; i++)
167 {
168 m_aDayTimeCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, m_aDayTimeCurve[i].m_Curve);
169 }
170 }
171
172 //------------------------------------------------------------------------------------------------
173 private int GetDensityMax(int soundGroup)
174 {
175 return m_aSpawnDef[soundGroup].m_iDensity;
176 }
177
178 //------------------------------------------------------------------------------------------------
179 private void UpdateSoundSequence(float worldTime, vector cameraPos)
180 {
181 for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
182 {
183 SCR_SoundHandle soundHandle = m_aSoundHandle[i];
184
185 if (worldTime > soundHandle.m_aRepTime[soundHandle.m_iRepTimeIdx])
186 {
187 // Set SoundName signal
188 if (m_iSoundNameSignalIdx != INVALID)
189 m_LocalSignalsManager.SetSignalValue(m_iSoundNameSignalIdx, soundHandle.m_SoundDef.m_eSoundName);
190
191 // Set Distance signal
193 m_LocalSignalsManager.SetSignalValue(m_iDistanceSignalIdx, vector.Distance(cameraPos, soundHandle.m_aMat[3]));
194
195 // Play sound event
196 m_AmbientSoundsComponent.SoundEventTransform(m_aSoundGroup[soundHandle.m_iSoundGroup].m_sSoundEvent, soundHandle.m_aMat);
197
198#ifdef ENABLE_DIAG
199 soundHandle.m_SoundDef.m_iCount++;
200#endif
201
202 // Remove if last event in the sequence
203 soundHandle.m_iRepTimeIdx ++;
204 if (soundHandle.m_aRepTime.Count() == soundHandle.m_iRepTimeIdx)
205 m_aSoundHandle.Remove(i);
206 }
207 }
208 }
209
210 //------------------------------------------------------------------------------------------------
211 private void RemoveOutOfRangeSound(vector cameraPos)
212 {
213 for (int i = m_aSoundHandle.Count() - 1; i >= 0; i--)
214 {
215 SCR_SoundHandle soundHandle = m_aSoundHandle[i];
216 SCR_SpawnDef spawnDef = m_aSpawnDef[soundHandle.m_iSoundGroup];
217
218 if (!Math.IsInRange(vector.Distance(cameraPos, soundHandle.m_aMat[3]), spawnDef.m_iPlayDistMin, spawnDef.m_iPlayDistMax))
219 m_aSoundHandle.Remove(i);
220 }
221 }
222
223 //------------------------------------------------------------------------------------------------
228 private void UpdateSoundGroup(float worldTime, vector camPos, int soundGroup)
229 {
230 // Check if density modified by rain, wind and time of day was reached
231 if (m_aDensity[soundGroup] >= GetDensityMax(soundGroup) * m_aDensityModifier[soundGroup])
232 return;
233
234 // Generate sound position
235 vector vPos;
236 int soundType = INVALID;
237
238 m_aSoundGroup[soundGroup].GetSoundTypeAndPosition(this, camPos, m_aSpawnDef[soundGroup].m_iSpawnDist, soundType, vPos);
239
240 if (soundType == INVALID)
241 return;
242
243 // Get random sound definition
244 int soundDef = GetRandomSoundDef(m_aSoundGroup[soundGroup].m_aSoundType[soundType], worldTime);
245
246 if (soundDef == INVALID)
247 return;
248
249 // Create sound event sequence
250 vector mat[4];
251 Math3D.MatrixIdentity4(mat);
252 mat[3] = vPos;
253
254 SCR_SoundHandle soundHandle = new SCR_SoundHandle(soundGroup, soundType, soundDef, mat, m_aSoundGroup, worldTime);
255 m_aSoundHandle.Insert(soundHandle);
256
257 // Set CoolDownEnd time
258 float timeOfDayFactor = m_aDayTimeCurveValue[soundHandle.m_SoundDef.m_eDayTimeCurve];
259 timeOfDayFactor = (1 - Math.Clamp(timeOfDayFactor, 0, 1));
260 timeOfDayFactor = Math.Pow(timeOfDayFactor, 3) * 4 + 1;
261
262 if (soundHandle.m_SoundDef.m_bAddSequenceLength)
263 soundHandle.m_SoundDef.m_fCoolDownEnd = worldTime + soundHandle.GetSequenceLenght(worldTime) + soundHandle.m_SoundDef.m_iCoolDown * timeOfDayFactor;
264 else
265 soundHandle.m_SoundDef.m_fCoolDownEnd = worldTime + soundHandle.m_SoundDef.m_iCoolDown * timeOfDayFactor;
266 }
267
268 //------------------------------------------------------------------------------------------------
269 private int GetRandomSoundDef(SCR_SoundType soundType, float worldTime)
270 {
271 int size = soundType.m_aSoundDef.Count();
272 if (size == 0)
273 return INVALID;
274
275 int offset = Math.RandomIntInclusive(0, size - 1);
276
277 for (int i = 0; i < size; i++)
278 {
279 int idx = i + offset;
280 if (idx >= size)
281 idx -= size;
282
283 if (m_aDayTimeCurveValue[soundType.m_aSoundDef[idx].m_eDayTimeCurve] > 0 && soundType.m_aSoundDef[idx].m_fCoolDownEnd < worldTime)
284 return idx;
285 }
286
287 return INVALID;
288 }
289
290 //------------------------------------------------------------------------------------------------
291 private void UpdateDensity()
292 {
293 // Clear density
294 const int count = m_aDensity.Count();
295 for (int i = 0; i < count; i++)
296 {
297 m_aDensity[i] = 0;
298 }
299
300 // Set density
301 foreach (SCR_SoundHandle soundHandle : m_aSoundHandle)
302 {
303 const int soundGroup = soundHandle.m_iSoundGroup;
304 const int soundType = soundHandle.m_iSoundType;
305
306 const float densityMultiplier = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_fDensityMultiplier;
307 m_aDensity[soundGroup] = m_aDensity[soundGroup] + densityMultiplier * soundHandle.m_fDensity;
308 }
309 }
310
311 //------------------------------------------------------------------------------------------------
312 private float Interpolate01(float in, float Xmin, float Xmax)
313 {
314 if (in <= Xmin)
315 return 0;
316
317 if (in >= Xmax)
318 return 1;
319
320 return (in - Xmin) / (Xmax - Xmin);
321 }
322
323 //------------------------------------------------------------------------------------------------
324 private void UpdateSignlsIdx()
325 {
326 m_iSunAngleSignalIdx = m_LocalSignalsManager.AddOrFindSignal(SUN_ANGLE_SIGNAL_NAME);
327 m_iSoundNameSignalIdx = m_LocalSignalsManager.AddOrFindSignal(SOUND_NAME_SIGNAL_NAME);
329 m_iEnvironmentTypeSignalIdx = m_LocalSignalsManager.AddOrFindSignal(ENVIRONMENT_TYPE_SIGNAL_NAME);
330
331 m_iRainIntensitySignalIdx = m_GlobalSignalsManager.AddOrFindSignal(RAIN_INTENSITY_SIGNAL_NAME);
332 m_iWindSpeedSignalIdx = m_GlobalSignalsManager.AddOrFindSignal(WIND_SPEED_SIGNAL_NAME);
333 }
334
335 //------------------------------------------------------------------------------------------------
336 private void LoadConfigs(SCR_AmbientSoundsComponent ambientSoundsComponent)
337 {
338 foreach (SCR_RandomPositionalSoundsDef def: m_aRandomPositionalSoundsDef)
339 {
340 SCR_SoundGroup soundGrop;
341 if (def.m_SoundGroupResource != string.Empty)
342 {
343 Resource holder = BaseContainerTools.LoadContainer(def.m_SoundGroupResource);
344 if (holder)
345 soundGrop = SCR_SoundGroup.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
346 }
347
348 if (!soundGrop)
349 {
350 ambientSoundsComponent.SetScriptedMethodsCall(false);
351 Print("AUDIO: SCR_AmbientSoundsComponent: Missing Ambience Sound Gropu Config", LogLevel.WARNING);
352 return;
353 }
354
355 m_aSoundGroup.Insert(soundGrop);
356
357 // ---
358 SCR_SpawnDef spawnDef;
359 if (def.m_SpawnDefResource != string.Empty)
360 {
361 Resource holder = BaseContainerTools.LoadContainer(def.m_SpawnDefResource);
362 if (holder)
363 spawnDef = SCR_SpawnDef.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
364 }
365
366 if (!spawnDef)
367 {
368 ambientSoundsComponent.SetScriptedMethodsCall(false);
369 Print("AUDIO: SCR_AmbientSoundsComponent: Missing Spawn Definition Config", LogLevel.WARNING);
370 return;
371 }
372
373 m_aSpawnDef.Insert(spawnDef);
374 }
375
376 // ---
377 SCR_TerrainDefConfig soundTerrainDefinitionConfig;
378 if (m_TerrainDefinitionResource != string.Empty)
379 {
380 Resource holder = BaseContainerTools.LoadContainer(m_TerrainDefinitionResource);
381 if (holder)
382 soundTerrainDefinitionConfig = SCR_TerrainDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
383 }
384
385 if (!soundTerrainDefinitionConfig)
386 {
387 ambientSoundsComponent.SetScriptedMethodsCall(false);
388 Print("AUDIO: SCR_AmbientSoundsComponent: Missing Sound Definition Terrain Config", LogLevel.WARNING);
389 return;
390 }
391
392 m_aTerrainDef = soundTerrainDefinitionConfig.m_aTerrainDef;
393
394 // ---
395 SCR_DayTimeCurveDefConfig ambientSoundsDayTimeCurveDefinitionConfig;
396 if (m_DayTimeCurveResource != string.Empty)
397 {
398 Resource holder = BaseContainerTools.LoadContainer(m_DayTimeCurveResource);
399 if (holder)
400 ambientSoundsDayTimeCurveDefinitionConfig = SCR_DayTimeCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
401 }
402
403 if (!ambientSoundsDayTimeCurveDefinitionConfig)
404 {
405 ambientSoundsComponent.SetScriptedMethodsCall(false);
406 Print("AUDIO: SCR_AmbientSoundsComponent: Missing Daytime Curve Deffinition Config", LogLevel.WARNING);
407 return;
408 }
409
410 m_aDayTimeCurve = ambientSoundsDayTimeCurveDefinitionConfig.m_aDayTimeCurve;
411
412 // ---
413 SCR_WindCurveDefConfig ambientSoundsWindDefinitionConfig;
414 if (m_WindCurveResource != string.Empty)
415 {
416 Resource holder = BaseContainerTools.LoadContainer(m_WindCurveResource);
417 if (holder)
418 ambientSoundsWindDefinitionConfig = SCR_WindCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
419 }
420
421 if (!ambientSoundsWindDefinitionConfig)
422 {
423 ambientSoundsComponent.SetScriptedMethodsCall(false);
424 Print("AUDIO: SCR_AmbientSoundsComponent: Missing Wind Curve Definition Config", LogLevel.WARNING);
425 return;
426 }
427
428 m_aWindModifier = ambientSoundsWindDefinitionConfig.m_aWindModifier;
429 }
430
431 //------------------------------------------------------------------------------------------------
432#ifdef ENABLE_DIAG
433 private const int STRING_LENGTH = 20;
434 private const int PANEL_WIDTH = 20;
435 private const int PANEL_HEIGHT = 20;
436
437 ref array<bool> m_soundGroupCheck;
438 ref array<ref array<bool>> m_soundTypeCheck;
439
440 //------------------------------------------------------------------------------------------------
442 void AmbientSignalsDebug()
443 {
444 DbgUI.Begin("Ambient Sounds Signals", 178, 0);
445 DbgUI.Text(SUN_ANGLE_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iSunAngleSignalIdx).ToString());
446 DbgUI.Text(SOUND_NAME_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iSoundNameSignalIdx).ToString());
447 DbgUI.Text(DISTANCE_SIGNAL_NAME + ": " + m_LocalSignalsManager.GetSignalValue(m_iDistanceSignalIdx).ToString());
448 DbgUI.End();
449 }
450
451 //------------------------------------------------------------------------------------------------
453 void DensityDebug()
454 {
455 DbgUI.Begin("Density", 420, 0);
456 for (int i = 0, count = m_aSpawnDef.Count(); i < count; i++)
457 {
458 DbgUI.Text(m_aSoundGroup[i].m_sSoundEvent + ": " + m_aDensity[i].ToString() + " / " + (Math.Round(GetDensityMax(i) * m_aDensityModifier[i])).ToString());
459 }
460 DbgUI.End();
461 }
462
463 //------------------------------------------------------------------------------------------------
466 void RandomPositionalSoundDebug(float worldTime)
467 {
468 int defaultColor = ARGB(255, 50, 50, 50);
469 int blackColor = ARGB(255, 0, 0, 0);
470 int availableColor = ARGB(255, 0, 0, 255);
471 int playingColor = ARGB(255, 255, 255, 0);
472 int wrongTimeColor = ARGB(255, 125, 125, 125);
473 int inCooldownColor = ARGB(255, 255, 0, 255);
474
475 DbgUI.Begin("Random Ambient Sounds", 0, 185);
476
477 DbgUI.Panel("av", PANEL_WIDTH, PANEL_HEIGHT, availableColor);
478 DbgUI.SameLine();
479 DbgUI.Text("Available");
480 DbgUI.SameLine();
481 DbgUI.Panel("pl", PANEL_WIDTH, PANEL_HEIGHT, playingColor);
482 DbgUI.SameLine();
483 DbgUI.Text("Playing");
484 DbgUI.SameLine();
485 DbgUI.Panel("wt", PANEL_WIDTH, PANEL_HEIGHT, wrongTimeColor);
486 DbgUI.SameLine();
487 DbgUI.Text("WrongTime");
488 DbgUI.SameLine();
489 DbgUI.Panel("in", PANEL_WIDTH, PANEL_HEIGHT, inCooldownColor);
490 DbgUI.SameLine();
491 DbgUI.Text("InCooldown");
492
493 // Prepare arrays for check widgets
494 if (!m_soundGroupCheck)
495 {
496 m_soundGroupCheck = {};
497 m_soundGroupCheck.Resize(m_aSpawnDef.Count());
498 }
499 if (!m_soundTypeCheck)
500 {
501 m_soundTypeCheck = {};
502 m_soundTypeCheck.Resize(m_aSpawnDef.Count());
503
504 for (int soundGroup = 0; soundGroup < m_aSpawnDef.Count(); soundGroup++)
505 {
506 m_soundTypeCheck[soundGroup] = {};
507 int soundTypeCount = m_aSoundGroup[soundGroup].m_aSoundType.Count();
508 m_soundTypeCheck[soundGroup].Resize(soundTypeCount);
509 }
510 }
511
512 for (int soundGroup = 0; soundGroup < m_aSpawnDef.Count(); soundGroup++)
513 {
514 // Get SoundGropu name
515 string name = m_aSoundGroup[soundGroup].m_sSoundEvent;
516 name = NormalizeLength(name);
517 name = soundGroup.ToString() + ". " + name;
518
519 // Show number of playing sounds
520 const int limitCount = 8; // TODO: check for good const usage
521 int playingCount = 0;
522
523 bool bSoundTypeChecked = m_soundGroupCheck[soundGroup];
524 DbgUI.Check(name, bSoundTypeChecked);
525 m_soundGroupCheck[soundGroup] = bSoundTypeChecked;
526
527 for (int i = 0; i < m_aSoundHandle.Count(); i++)
528 {
529 if (m_aSoundHandle[i].m_iSoundGroup == soundGroup)
530 playingCount ++;
531 }
532
533 for (int i = 0; i < limitCount; i++)
534 {
535 int color = defaultColor;
536
537 if (i < playingCount)
538 {
539 color = playingColor;
540 }
541
542 DbgUI.SameLine();
543 DbgUI.Panel(soundGroup.ToString() + "." + i.ToString(), PANEL_WIDTH, PANEL_HEIGHT, color);
544 }
545
546 if (bSoundTypeChecked)
547 {
548 int soundTypeCount = m_aSoundGroup[soundGroup].m_aSoundType.Count();
549
550
551 for (int soundType = 0; soundType < soundTypeCount; soundType++)
552 {
553 // Get SoundType name
554 string soundTypeName;
555 if (SCR_TreeSoundGroup.Cast(m_aSoundGroup[soundGroup]))
556 {
557 if (soundType == 0)
558 soundTypeName = "CONIFER";
559 else
560 soundTypeName = "LEAFY";
561 }
562 else if (SCR_TerrainSoundGroup.Cast(m_aSoundGroup[soundGroup]))
563 soundTypeName = typename.EnumToString(ETerrainType, soundType);
564 else
565 soundTypeName = typename.EnumToString(ESoundMapType, soundType);
566
567 soundTypeName = NormalizeLength(soundTypeName);
568
569 DbgUI.Panel(soundGroup.ToString() + soundType.ToString(), PANEL_WIDTH, PANEL_HEIGHT, blackColor);
570 DbgUI.SameLine();
571
572 bool bSoundGroupChecked = m_soundTypeCheck[soundGroup][soundType];
573 DbgUI.Check(soundGroup.ToString() + "." + soundType.ToString() + ". " + soundTypeName, bSoundGroupChecked);
574 m_soundTypeCheck[soundGroup][soundType] = bSoundGroupChecked;
575
576 DbgUI.SameLine();
577
578 int size = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count();
579 int available = 0;
580 for (int idx = 0; idx < size; idx++)
581 {
582 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)
583 available++;
584 }
585
586 DbgUI.Text(soundGroup.ToString() + "." + soundType.ToString() + ". " + "Available :" + available.ToString() + " of (" + m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count() + ")");
587
588 if (bSoundGroupChecked)
589 {
590 int soundDefCount = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count();
591
592 for (int soundDef = 0; soundDef < soundDefCount; soundDef++)
593 {
594 int color = defaultColor;
595 string aditionalInfo = "";
596
597 // -----------------------
598 // -----Status panel------
599 // -----------------------
600
601 // Tag if sound is in cooldown
602 if (m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd > worldTime)
603 {
604 color = inCooldownColor;
605 aditionalInfo = " | Coldown ends in : " + Math.Round((m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd - worldTime) * 0.001).ToString();
606
607 float timeOfDayFactor = m_aDayTimeCurveValue[m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eDayTimeCurve];
608 timeOfDayFactor = (1 - Math.Clamp(timeOfDayFactor, 0, 1));
609 timeOfDayFactor = Math.Pow(timeOfDayFactor, 3) * 4 + 1;
610 timeOfDayFactor = Math.Round(timeOfDayFactor * 100) * 0.01;
611
612 aditionalInfo = aditionalInfo + " | TFactor : " + timeOfDayFactor.ToString();
613 }
614
615 EDayTimeCurve m_eDayTimeCurve = m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eDayTimeCurve;
616
617 // Tag sounds that can not play in given time of day
618 if (m_aDayTimeCurveValue[m_eDayTimeCurve] <= 0)
619 color = wrongTimeColor;
620
621 // Tag available
622 if (m_aDayTimeCurveValue[m_eDayTimeCurve] > 0 && m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_fCoolDownEnd <= worldTime)
623 color = availableColor;
624
625 DbgUI.Panel(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString(), PANEL_WIDTH * 2 + 5, PANEL_HEIGHT, color);
626
627 // -----------------------
628 // -Sound definition name-
629 // -----------------------
630
631 string soundDefinitionName = typename.EnumToString(ESoundName, m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef[soundDef].m_eSoundName);
632 soundDefinitionName = NormalizeLength(soundDefinitionName);
633 DbgUI.SameLine();
634 DbgUI.Text(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString() + ". " + soundDefinitionName + " ");
635
636 // -----------------------
637 // - Number of instances -
638 // -----------------------
639
640 int instanceCount = 0;
641 float playbackEnd = 0;
642
643 foreach (SCR_SoundHandle sh: m_aSoundHandle)
644 {
645 if (sh.m_iSoundGroup == soundGroup && sh.m_iSoundType == soundType && sh.m_iSoundDef == soundDef)
646 {
647 instanceCount ++;
648
649 if (playbackEnd < Math.Round(sh.m_aRepTime[sh.m_aRepTime.Count() - 1] - worldTime))
650 {
651 playbackEnd = Math.Round(sh.m_aRepTime[sh.m_aRepTime.Count() - 1] - worldTime);
652 }
653 }
654 }
655
656 playbackEnd = Math.Round(playbackEnd * 0.001);
657
658 if (playbackEnd > 0)
659 {
660 aditionalInfo = aditionalInfo + " | Playback ends in : " + playbackEnd.ToString();
661 }
662
663 for (int j = 0; j < instanceCount; j++)
664 {
665 DbgUI.SameLine();
666 DbgUI.Panel(soundGroup.ToString() + "." + soundType.ToString() + "." + soundDef.ToString() + "Play" + j.ToString(), PANEL_WIDTH, PANEL_HEIGHT, playingColor);
667 }
668
669 // -----------------------
670 // -----Aditional info----
671 // -----------------------
672
673 DbgUI.SameLine();
674 DbgUI.Text(aditionalInfo);
675 }
676 }
677 }
678 }
679 }
680
681 DbgUI.End();
682 }
683
684 //------------------------------------------------------------------------------------------------
685 private string NormalizeLength(string name)
686 {
687 int length = name.Length();
688 string s = name;
689
690 if (length <= STRING_LENGTH)
691 {
692 for (int i = 0; i < (STRING_LENGTH - length); i++)
693 {
694 s = s + " ";
695 }
696 }
697 else
698 s = s.Substring(0, STRING_LENGTH * 0.5 - 2) + "...." + s.Substring(length - STRING_LENGTH * 0.5, STRING_LENGTH * 0.5);
699
700 return s;
701 }
702
703 //------------------------------------------------------------------------------------------------
704 override void ReloadConfig()
705 {
706 super.ReloadConfig();
707
708 m_aSoundGroup.Clear();
709 m_aSpawnDef.Clear();
710
711 foreach (SCR_RandomPositionalSoundsDef def: m_aRandomPositionalSoundsDef)
712 {
713 SCR_SoundGroup soundGrop;
714 if (def.m_SoundGroupResource != string.Empty)
715 {
716 Resource holder = BaseContainerTools.LoadContainer(def.m_SoundGroupResource);
717 if (holder)
718 soundGrop = SCR_SoundGroup.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
719 }
720
721 if (soundGrop)
722 m_aSoundGroup.Insert(soundGrop);
723
724 // ---
725 SCR_SpawnDef spawnDef;
726 if (def.m_SpawnDefResource != string.Empty)
727 {
728 Resource holder = BaseContainerTools.LoadContainer(def.m_SpawnDefResource);
729 if (holder)
730 spawnDef = SCR_SpawnDef.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
731 }
732
733 if (spawnDef)
734 m_aSpawnDef.Insert(spawnDef);
735 }
736
737 // ---
738 SCR_TerrainDefConfig soundTerrainDefinitionConfig;
739 if (m_TerrainDefinitionResource != string.Empty)
740 {
741 Resource holder = BaseContainerTools.LoadContainer(m_TerrainDefinitionResource);
742 if (holder)
743 soundTerrainDefinitionConfig = SCR_TerrainDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
744 }
745
746 if (soundTerrainDefinitionConfig)
747 m_aTerrainDef = soundTerrainDefinitionConfig.m_aTerrainDef;
748
749 // ---
750 SCR_DayTimeCurveDefConfig ambientSoundsDayTimeCurveDefinitionConfig;
751 if (m_DayTimeCurveResource != string.Empty)
752 {
753 Resource holder = BaseContainerTools.LoadContainer(m_DayTimeCurveResource);
754 if (holder)
755 ambientSoundsDayTimeCurveDefinitionConfig = SCR_DayTimeCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
756 }
757
758 if (!ambientSoundsDayTimeCurveDefinitionConfig)
759 m_aDayTimeCurve = ambientSoundsDayTimeCurveDefinitionConfig.m_aDayTimeCurve;
760
761 // ---
762 SCR_WindCurveDefConfig ambientSoundsWindDefinitionConfig;
763 if (m_WindCurveResource != string.Empty)
764 {
765 Resource holder = BaseContainerTools.LoadContainer(m_WindCurveResource);
766 if (holder)
767 ambientSoundsWindDefinitionConfig = SCR_WindCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
768 }
769
770 if (ambientSoundsWindDefinitionConfig)
771 m_aWindModifier = ambientSoundsWindDefinitionConfig.m_aWindModifier;
772
773 m_aSoundHandle.Clear();
774 }
775
776 //------------------------------------------------------------------------------------------------
777 private void PlaySound(float worldTime)
778 {
779 DbgUI.Begin("Play Sound", 0, 0);
780
781 int soundGroup = 3;
782 int soundType = 2;
783 int soundDef = 0;
784 float distanceFactor = 0.15;
785 DbgUI.InputInt("Sound Group:", soundGroup, 50);
786 DbgUI.InputInt("Sound Type :", soundType, 50);
787 DbgUI.InputInt("Sound Def :", soundDef, 50);
788 DbgUI.InputFloat("Dist Factor:", distanceFactor, 50);
789
790 bool play = DbgUI.Button("Play");
791 DbgUI.SameLine();
792 bool clear = DbgUI.Button("Clear");
793
794 if (play)
795 {
796 // Check if sound definition is correct
797 if (soundGroup >= m_aSoundGroup.Count() || soundType >= m_aSoundGroup[soundGroup].m_aSoundType.Count() || soundDef >= m_aSoundGroup[soundGroup].m_aSoundType[soundType].m_aSoundDef.Count())
798 return;
799
800 // Get camera transf
801 vector mat[4];
802 GetGame().GetCameraManager().CurrentCamera().GetTransform(mat);
803
804 // Get direction
805 vector yaw = mat[0];
806 float angle = yaw.ToYaw();
807 angle -= 90;
808 yaw = vector.FromYaw(angle);
809
810 // Get sound position
811 float dist = Math.Lerp(m_aSpawnDef[soundGroup].m_iPlayDistMin, m_aSpawnDef[soundGroup].m_iPlayDistMax, distanceFactor);
812 mat[3] = mat[3] + yaw * dist;
813
814 // Add sound to pool
815 SCR_SoundHandle soundHandle = new SCR_SoundHandle(soundGroup, soundType, soundDef, mat, m_aSoundGroup, worldTime);
816 m_aSoundHandle.Insert(soundHandle);
817 }
818
819 if (clear)
820 m_aSoundHandle.Clear();
821
822 DbgUI.End();
823 }
824
825#endif
826
827 //------------------------------------------------------------------------------------------------
828 override void OnPostInit(SCR_AmbientSoundsComponent ambientSoundsComponent, SignalsManagerComponent signalsManagerComponent)
829 {
830 super.OnPostInit(ambientSoundsComponent, signalsManagerComponent);
831
832 LoadConfigs(ambientSoundsComponent);
833
834 m_LocalSignalsManager = signalsManagerComponent;
835 m_GlobalSignalsManager = GetGame().GetSignalsManager();
836 m_AmbientSoundsComponent = ambientSoundsComponent;
837
838 int count = m_aSpawnDef.Count();
839 m_aDensity.Resize(count);
840 m_aAngleOffset.Resize(count);
841 m_aDensityModifier.Resize(count);
842
843 UpdateSignlsIdx();
844 m_World = ChimeraWorld.CastFrom(GetGame().GetWorld());
845
846#ifdef ENABLE_DIAG
847 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS, "", "Random Ambient Sounds", "Sounds");
848#endif
849 }
850
851 //------------------------------------------------------------------------------------------------
852 override void OnInit()
853 {
854 super.OnInit();
855
856 UpdateGlobalModifiers();
857 }
858
859 //------------------------------------------------------------------------------------------------
860 // destructor
861 void ~SCR_RandomPositionalSounds()
862 {
863#ifdef ENABLE_DIAG
864 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS))
865 {
866 foreach (SCR_SoundGroup soundGroup : m_aSoundGroup)
867 {
868 foreach (SCR_SoundType soundType : soundGroup.m_aSoundType)
869 {
870 foreach (SCR_SoundDef soundDef : soundType.m_aSoundDef)
871 {
872 Print(typename.EnumToString(ESoundName, soundDef.m_eSoundName) + ": " + soundDef.m_iCount, LogLevel.NORMAL);
873 }
874 }
875 }
876 }
877
878 DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_SOUNDS_RANDOM_POSITIONAL_SOUNDS);
879#endif
880 }
881}
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ArmaReforgerScripted GetGame()
Definition game.c:1398
int size
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
void UpdateDebug()
EDayTimeCurve
const int DAY_TIME_CURVE_COUNT
void PlaySound(string soundName)
const string DISTANCE_SIGNAL_NAME
SCR_AmbientSoundsComponent m_AmbientSoundsComponent
SignalsManagerComponent m_LocalSignalsManager
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
ESoundName
Definition SCR_SoundDef.c:2
ref array< ref SCR_SoundType > m_aSoundType
string m_sSoundEvent
ETerrainType
const int WIND_CURVE_COUNT
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
@ INVALID
Missing components, or obstruction test was not possible.
proto external string ToString()
Plain C++ pointer, no weak pointers, no memory management.
proto int ARGB(int a, int r, int g, int b)