Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_LoopedPositionalSounds.c
Go to the documentation of this file.
1 [BaseContainerProps(configRoot: true)]
4 {
5  private const int MINIMUM_MOVE_DISTANCE_SQ = 2;
6  private const int INVALID = -1;
7  private const int LOOP_SOUND_HEIGHT_LIMIT = 25;
8  private const int LOOP_SOUND_COUNT = 9;
9  private const float BOUNDING_BOX_CROP_FACTOR = 0.3;
10  private const float BOUNDING_BOX_CROP_FACTOR_HEIGHT = 0.9;
11  private const int BUSH_LOOP_SOUND_COUNT_LIMIT = 4;
12  private const string ENTITY_SIZE_SIGNAL_NAME = "EntitySize";
13  private const string SEED_SIGNAL_NAME = "Seed";
14 
15  [Attribute("0.3", desc: "Ratio of bushes with insect sounds vs without")]
16  private float m_fBushCricketThreshold;
17 
18  private int m_iEntitySizeSignalIdx;
19  private int m_iSeedSignalIdx;
20 
22  private vector m_vCameraPosLooped;
23 
25  private ref array<IEntity> m_aClosestEntityID = {};
26 
28  private ref array<IEntity> m_aLoopedSoundID = {};
29 
31  private ref array<AudioHandle> m_aLoopedSoundAudioHandle = {};
32 
33  //------------------------------------------------------------------------------------------------
34  // Called by SCR_AmbientSoundComponent in UpdateSoundJob()
35  override void Update(float worldTime, vector cameraPos)
36  {
37  if (vector.DistanceSqXZ(m_vCameraPosLooped, cameraPos) < MINIMUM_MOVE_DISTANCE_SQ)
38  return;
39 
40  m_vCameraPosLooped = cameraPos;
41 
42  m_aClosestEntityID.Clear();
43 
44  //Get closest entities array
45  UpdateClosesEntitieyArray();
46 
47  // Stop sounds that are no longer among closest entities
48  StopLoopedSounds();
49 
50  // Play sounds on entities, that become closest
51  PlayLoopedSounds(cameraPos);
52  }
53 
54  //------------------------------------------------------------------------------------------------
55  private void StopLoopedSounds()
56  {
57  for (int i = m_aLoopedSoundID.Count() - 1; i >= 0; i--)
58  {
59  int index = m_aClosestEntityID.Find(m_aLoopedSoundID[i]);
60 
61  if (index == INVALID)
62  {
63  m_aLoopedSoundID.Remove(i);
64  m_AmbientSoundsComponent.Terminate(m_aLoopedSoundAudioHandle[i]);
65  m_aLoopedSoundAudioHandle.Remove(i);
66  }
67  }
68  }
69 
70  //------------------------------------------------------------------------------------------------
71  private void PlayLoopedSounds(vector cameraPos)
72  {
73  foreach(IEntity entity: m_aClosestEntityID)
74  {
75  if (entity == null)
76  continue;
77 
78  int index = m_aLoopedSoundID.Find(entity);
79 
80  if (index != INVALID)
81  continue;
82 
83  float foliageHight;
84  ETreeSoundTypes treeSoundType
85  GetTreeProperties(entity, treeSoundType, foliageHight);
86 
87  // Get event name
88  string eventName;
89 
90  if (treeSoundType == ETreeSoundTypes.Leafy)
91  {
92  eventName = GetTreeSoundEventName(foliageHight, treeSoundType);
93  }
94  else
95  {
96  vector v = entity.GetOrigin();
97  int seed = v[0] * v[2];
98  RandomGenerator ranGen = SCR_Math.GetMathRandomGenerator();
99  ranGen.SetSeed(seed);
100 
101  if (ranGen.RandFloat01() > m_fBushCricketThreshold)
102  {
103  float sampleSelector = Math.AbsInt(seed % 100) * 0.01;
104  m_LocalSignalsManager.SetSignalValue(m_iSeedSignalIdx, sampleSelector);
105  eventName = SCR_SoundEvent.SOUND_BUSH_CRICKETS_LP;
106  }
107  else
108  {
109  eventName = SCR_SoundEvent.SOUND_BUSH_LP;
110  }
111  }
112 
113  // Get sound position
114  vector mat[4];
115  Math3D.MatrixIdentity4(mat);
116 
117  // Get world bounding box
118  vector mins, maxs;
119  entity.GetWorldBounds(mins, maxs);
120 
121  // Get height
122  float BVHeight = (maxs[1] - mins[1] - foliageHight) * BOUNDING_BOX_CROP_FACTOR_HEIGHT;
123 
124  // Get average width
125  float widthX = (maxs[0] - mins[0]) * 0.5;
126  float widthZ = (maxs[2] - mins[2]) * 0.5;
127  float BVRadius = 0.5 * (widthX + widthZ) * BOUNDING_BOX_CROP_FACTOR;
128 
129  // Get center
130  mat[3][0] = mins[0] + widthX;
131  mat[3][1] = mins[1] + foliageHight + 0.5 * BVHeight;
132  mat[3][2] = mins[2] + widthZ;
133 
134  // Play sound
135  AudioHandle audioHandle = m_AmbientSoundsComponent.SoundEventTransform(eventName, mat);
136  if (!m_AmbientSoundsComponent.IsHandleValid(audioHandle))
137  continue;
138 
139  // Set BV parameters
140  AudioSystem.SetBoundingVolumeParams(audioHandle, AudioSystem.BV_Cylinder, BVRadius, BVHeight, 0);
141 
142  // Store references
143  m_aLoopedSoundID.Insert(entity);
144  m_aLoopedSoundAudioHandle.Insert(audioHandle);
145  }
146  }
147 
148  //------------------------------------------------------------------------------------------------
149  private void UpdateClosesEntitieyArray()
150  {
151  m_AmbientSoundsComponent.GetClosestEntities(EQueryType.TreeBush, BUSH_LOOP_SOUND_COUNT_LIMIT, m_aClosestEntityID);
152  m_AmbientSoundsComponent.GetClosestEntities(EQueryType.TreeLeafy, LOOP_SOUND_COUNT, m_aClosestEntityID);
153  }
154 
155  //------------------------------------------------------------------------------------------------
156  protected void GetTreeProperties(IEntity entity, out ETreeSoundTypes soundType, out float foliageHeight)
157  {
158  // Get tree entity
159  Tree tree = Tree.Cast(entity);
160  if (!tree)
161  return;
162 
163  // Get prefab data
164  TreeClass treeClass = TreeClass.Cast(tree.GetPrefabData());
165  if (!treeClass)
166  return;
167 
168  foliageHeight = treeClass.m_iFoliageHeight * entity.GetScale();
169  soundType = treeClass.SoundType;
170  }
171 
172  //------------------------------------------------------------------------------------------------
173  protected string GetTreeSoundEventName(float foliageHeight, ETreeSoundTypes treeSoundType)
174  {
175  if (foliageHeight < 3)
176  return SCR_SoundEvent.SOUND_LEAFYTREE_SMALL_LP;
177  else if (foliageHeight < 5)
178  return SCR_SoundEvent.SOUND_LEAFYTREE_MEDIUM_LP;
179  else if (foliageHeight < 7)
180  return SCR_SoundEvent.SOUND_LEAFYTREE_LARGE_LP;
181  else
182  return SCR_SoundEvent.SOUND_LEAFYTREE_VERYLARGE_LP;
183  }
184 
185  //------------------------------------------------------------------------------------------------
186  // Called by SCR_AmbientSoundComponent in EOnPostInit()
187  override void OnPostInit(SCR_AmbientSoundsComponent ambientSoundsComponent, SignalsManagerComponent signalsManagerComponent)
188  {
189  super.OnPostInit(ambientSoundsComponent, signalsManagerComponent);
190 
191  m_iEntitySizeSignalIdx = signalsManagerComponent.AddOrFindSignal(ENTITY_SIZE_SIGNAL_NAME);
192  m_iSeedSignalIdx = signalsManagerComponent.AddOrFindSignal(SEED_SIGNAL_NAME);
193  }
194 }
EQueryType
EQueryType
Definition: SCR_AmbientSoundsComponent.c:1
SCR_SoundEvent
Definition: SCR_SoundEvent.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
SCR_Math
Definition: SCR_Math.c:1
SCR_LoopedPositionalSounds
Handles looped sounds such as leaves rustles, or crickets played on entities close to camera.
Definition: SCR_LoopedPositionalSounds.c:3
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
SCR_AmbientSoundsComponent
Definition: SCR_AmbientSoundsComponent.c:17
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
SCR_AmbientSoundsEffect
Definition: SCR_AmbientSoundsEffect.c:2
BaseContainerProps
SCR_AIGoalReaction_Follow BaseContainerProps
Handles insects that are supposed to be spawned around selected prefabs defined in prefab names array...
Definition: SCR_AIGoalReaction.c:468