Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_RandomPositionalInsects.c
Go to the documentation of this file.
1 [BaseContainerProps(configRoot: true)]
4 {
5  [Attribute(defvalue: "900", UIWidgets.Slider, params: "100 100000 1", desc: "Random positional insects that exceed this range (squared distance) will be despawned")]
6  protected int m_iDespawnDistanceSq;
7 
8  [Attribute()]
9  protected ref array<ref SCR_RandomPositionalInsectsDef> m_aRandomPositionalInsectsDef;
10 
11  [Attribute("", UIWidgets.ResourceNamePicker, desc: "Daytime curves config", params: "conf")]
12  protected ResourceName m_sDayTimeCurve;
13 
14  [Attribute("", UIWidgets.ResourceNamePicker, desc: "Wind modifier curves config", params: "conf")]
15  protected ResourceName m_sWindCurve;
16 
17  // Configuration
18  protected ref array<ref SCR_InsectGroup> m_aInsectGroup = {};
19  protected ref array<ref SCR_InsectSpawnDef> m_aSpawnDef = {};
20  protected ref array<ref SCR_DayTimeCurveDef> m_aDayTimeCurve = {};
21  protected ref array<ref SCR_WindCurveDef> m_aWindModifier = {};
22 
23  // Components
24  protected SoundWorld m_SoundWorld;
25 
26  protected const int INVALID = -1;
27  protected int m_iUpdatedInsectGroupIdx;
28  protected ref array<int> m_aDensity = {};
29  protected ref array<float> m_aDensityModifier = {};
30  protected ref array<int> m_aAngleOffset = {};
31  protected float m_aDayTimeCurveValue[DAY_TIME_CURVE_COUNT];
32  protected float m_aWindCurveValue[WIND_CURVE_COUNT];
33 
34  protected ref array<ref SCR_InsectParticle> m_aParticles = {};
35 
36  //------------------------------------------------------------------------------------------------
37  // Called by SCR_AmbientInsectsComponent.Update()
38  override void Update(float worldTime, vector cameraPos, float timeOfDay, float rainIntensity)
39  {
40 
41  RemoveOutOfRangeParticles(cameraPos);
42  RemoveParticlesBasedOnTimeAndWeather(timeOfDay, rainIntensity);
43  UpdateInsectGroup(worldTime, cameraPos, m_iUpdatedInsectGroupIdx);
44 
45  m_iUpdatedInsectGroupIdx ++;
46  if (m_iUpdatedInsectGroupIdx < m_aInsectGroup.Count())
47  return;
48 
49  m_iUpdatedInsectGroupIdx = 0;
50 
51  UpdateGlobalModifiers(timeOfDay, rainIntensity);
52  }
53 
54  //------------------------------------------------------------------------------------------------
58  protected void UpdateGlobalModifiers(float timeOfDay, float rainIntensity)
59  {
60  UpdateDensity();
61 
62  //Update values of wind modifiers curves
63  float windSpeedScaled = Math.InverseLerp(SCR_AmbientSoundsComponent.WINDSPEED_MIN, SCR_AmbientSoundsComponent.WINDSPEED_MAX, m_AmbientInsectsComponent.GetWindSpeed());
64 
65  for (int i = 0; i < WIND_CURVE_COUNT; i++)
66  {
67  m_aWindCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(windSpeedScaled, m_aWindModifier[i].m_Curve);
68  }
69 
70  // Get modifiers for all sound types
71  int environmentType = m_AmbientInsectsComponent.GetEnvironmentType();
72 
73  foreach (int i, SCR_InsectSpawnDef spawnDef : m_aSpawnDef)
74  {
75  float modifier = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, spawnDef.m_TimeModifier);
76  modifier = modifier * SCR_AmbientSoundsComponent.GetPoint(rainIntensity, spawnDef.m_RainModifier);
77  m_aDensityModifier[i] = modifier * m_aWindCurveValue[spawnDef.m_eWindModifier];
78  }
79 
80  // Update values of day time curves
81  for (int i = 0; i < DAY_TIME_CURVE_COUNT; i++)
82  {
83  m_aDayTimeCurveValue[i] = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, m_aDayTimeCurve[i].m_Curve);
84  }
85  }
86 
87  //------------------------------------------------------------------------------------------------
90  protected int GetDensityMax(int insectGroup, int soundMapType)
91  {
92  if (soundMapType == 0)
93  return m_aSpawnDef[insectGroup].m_iSeaDensityMax;
94  else if (soundMapType == 1)
95  return m_aSpawnDef[insectGroup].m_iForestDensityMax;
96  else if (soundMapType == 2)
97  return m_aSpawnDef[insectGroup].m_iCityDensityMax;
98  else if (soundMapType == 3)
99  return m_aSpawnDef[insectGroup].m_iMeadowDensityMax;
100  else if (soundMapType == 4)
101  return m_aSpawnDef[insectGroup].m_iRiverDensityMax;
102  else if (soundMapType == 5)
103  return m_aSpawnDef[insectGroup].m_iRiverSlopeDensityMax;
104  else if (soundMapType == 6)
105  return m_aSpawnDef[insectGroup].m_iLakeDensityMax;
106  else
107  return m_aSpawnDef[insectGroup].m_iCoastDensityMax;
108  }
109 
110  //------------------------------------------------------------------------------------------------
113  protected void RemoveOutOfRangeParticles(vector cameraPos)
114  {
115  for (int i = m_aParticles.Count() - 1; i >= 0; i--)
116  {
117  if (vector.DistanceSqXZ(m_aParticles[i].m_vPosition, cameraPos) >= m_iDespawnDistanceSq)
118  {
119  if (m_aParticles[i].m_AudioHandle)
120  m_AmbientSoundsComponent.TerminateLooped(m_aParticles[i].m_AudioHandle);
121 
122  m_aParticles.Remove(i);
123  }
124  }
125  }
126 
127  //------------------------------------------------------------------------------------------------
131  protected void RemoveParticlesBasedOnTimeAndWeather(float timeOfDay, float rainIntensity)
132  {
133  for (int i = m_aParticles.Count() - 1; i >= 0; i--)
134  {
135  float dayTimeCurve = SCR_AmbientSoundsComponent.GetPoint(timeOfDay, m_aSpawnDef[m_aParticles[i].m_iSoundGroup].m_TimeModifier);
136  float rainIntensityCurve = SCR_AmbientSoundsComponent.GetPoint(rainIntensity, m_aSpawnDef[m_aParticles[i].m_iSoundGroup].m_RainModifier);
137  if (dayTimeCurve <= 0 || rainIntensityCurve <= 0)
138  {
139  if (m_aParticles[i].m_AudioHandle)
140  m_AmbientSoundsComponent.TerminateLooped(m_aParticles[i].m_AudioHandle);
141 
142  m_aParticles.Remove(i);
143  }
144  }
145  }
146 
147  //------------------------------------------------------------------------------------------------
150  protected void RandomizeAnimation(IEntity entity)
151  {
152  AnimationPlayerComponent animComponent = AnimationPlayerComponent.Cast(entity.FindComponent(AnimationPlayerComponent));
153  if (!animComponent)
154  return;
155 
156  SCR_AnimationResourceHolderComponent animResourceHolder = SCR_AnimationResourceHolderComponent.Cast(entity.FindComponent(SCR_AnimationResourceHolderComponent));
157  if (!animResourceHolder)
158  return;
159 
160  animComponent.Prepare(animResourceHolder.m_sAnimation, Math.RandomFloatInclusive(1, 5), 1, true);
161  animComponent.Play();
162  }
163 
164  //------------------------------------------------------------------------------------------------
169  protected void UpdateInsectGroup(float worldTime, vector camPos, int insectGroup)
170  {
171  // Generate sound position
172  vector vPos;
173  int insectType = INVALID;
174  vPos = GenerateRandomPosition(insectGroup, camPos);
175  insectType = GetSoundMapTypeFromTerrain(vPos, camPos);
176  if (insectType == INVALID)
177  return;
178 
179  // Return, if density was reached
180  // Config density modified by time, wind and rain modifiers
181  if (m_aDensity[insectGroup] > GetDensityMax(insectGroup, insectType) * m_aDensityModifier[insectGroup])
182  return;
183 
184  // Get random sound definition
185  SCR_InsectDef insectDef;
186  if (m_aInsectGroup[insectGroup].m_aInsectType.IsIndexValid(insectType))
187  insectDef = GetRandomInsectDef(m_aInsectGroup[insectGroup].m_aInsectType[insectType]);
188 
189  if (!insectDef)
190  return;
191 
192  string particleName = insectDef.m_sParticleEffect;
193  string soundName = insectDef.m_sSoundName;
194  ResourceName prefabName = insectDef.m_sPrefabName;
195 
196  ParticleEffectEntitySpawnParams spawnParams();
197  spawnParams.Transform[3] = vPos;
198 
199  SCR_InsectParticle particle = new SCR_InsectParticle();
200  particle.m_iSoundGroup = insectGroup;
201  particle.m_vPosition = vPos;
202  if (Math.RandomIntInclusive(0, 100) <= m_aRandomPositionalInsectsDef[insectGroup].m_iSpawnChance)
203  {
204  if (!soundName.IsEmpty())
205  particle.m_AudioHandle = m_AmbientSoundsComponent.SoundEventLooped(soundName, spawnParams.Transform);
206 
207  if (!prefabName.IsEmpty())
208  {
209  Resource resource = Resource.Load(insectDef.m_sPrefabName);
210  if (resource)
211  {
212  EntitySpawnParams entitySpawnParams = new EntitySpawnParams;
213  entitySpawnParams.Transform = spawnParams.Transform;
214  entitySpawnParams.TransformMode = spawnParams.TransformMode;
215 
216  particle.m_InsectEntity = GetGame().SpawnEntityPrefab(resource, GetGame().GetWorld(), entitySpawnParams);
217  if (particle.m_InsectEntity)
218  {
219  particle.m_InsectEntity.SetVComponentFlags(VCFlags.DYNAMICBBOX);
220  RandomizeAnimation(particle.m_InsectEntity);
221  }
222  }
223  }
224  else if (!particleName.IsEmpty())
225  {
226  particle.m_ParticleEffect = ParticleEffectEntity.SpawnParticleEffect(insectDef.m_sParticleEffect, spawnParams);
227  }
228 
229 #ifdef ENABLE_DIAG
230  if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_AMBIENT_LIFE))
231  {
232  if (!soundName.IsEmpty())
233  particle.m_DebugShape = Shape.CreateSphere(COLOR_GREEN, ShapeFlags.NOZWRITE | ShapeFlags.WIREFRAME, spawnParams.Transform[3], 0.2);
234  else
235  particle.m_DebugShape = Shape.CreateSphere(COLOR_BLUE, ShapeFlags.NOZWRITE | ShapeFlags.WIREFRAME, spawnParams.Transform[3], 0.2);
236  }
237 #endif
238  }
239 
240  m_aParticles.Insert(particle);
241  }
242 
243  //------------------------------------------------------------------------------------------------
248  protected vector GenerateRandomPosition(int insectGroup, vector camPos)
249  {
250  // Angle for random position is rotated by 40 deg for each GenerateRandomPosition() call
251  float angle = m_aAngleOffset[insectGroup] * 40;
252 
253  m_aAngleOffset[insectGroup] = m_aAngleOffset[insectGroup] + 1;
254  if (m_aAngleOffset[insectGroup] > 9)
255  m_aAngleOffset[insectGroup] = 0;
256 
257  vector vPos = vector.FromYaw(angle) * Math.RandomFloat(10, 25);
258 
259  return vPos + camPos;
260  }
261 
262  //------------------------------------------------------------------------------------------------
265  protected SCR_InsectDef GetRandomInsectDef(SCR_InsectType insectType)
266  {
267  if (!insectType)
268  return null;
269 
270  int size = insectType.m_aInsectDef.Count();
271  if (size == 0)
272  return null;
273 
274  int offset = Math.RandomIntInclusive(0, size - 1);
275 
276  for (int i = 0; i < size; i++)
277  {
278  int idx = i + offset;
279  if (idx >= size)
280  idx -= size;
281 
282  if (m_aDayTimeCurveValue[insectType.m_aInsectDef[idx].m_eDayTimeCurve] > 0)
283  return insectType.m_aInsectDef[idx];
284  }
285 
286  return null;
287  }
288 
289  //------------------------------------------------------------------------------------------------
293  protected int GetSoundMapTypeFromTerrain(inout vector worldPos, vector camPos)
294  {
295  ChimeraWorld world = ChimeraWorld.CastFrom(m_AmbientInsectsComponent.GetOwner().GetWorld());
296  if (!world)
297  return INVALID;
298 
299  SoundWorld soundWorld = world.GetSoundWorld();
300  if (!soundWorld)
301  return INVALID;
302 
303  // We are getting these values twice - once for randomly found position around player, second on the camera position
304  float seaCam, forestCam, cityCam, meadowCam;
305  soundWorld.GetMapValuesAtPos(camPos, seaCam, forestCam, cityCam, meadowCam);
306 
307  float seaPos, forestPos, cityPos, meadowPos;
308  soundWorld.GetMapValuesAtPos(worldPos, seaPos, forestPos, cityPos, meadowPos);
309 
310  float riverCam, riverSlopeCam, lakeCam, coastCam;
311  soundWorld.GetMapValuesAdvAtPos(camPos, riverCam, riverSlopeCam, lakeCam, coastCam);
312 
313  float riverPos, riverSlopePos, lakePos, coastPos;
314  soundWorld.GetMapValuesAdvAtPos(worldPos, riverPos, riverSlopePos, lakePos, coastPos);
315 
316  array<float> valuesPos = {seaPos, forestPos, cityPos, meadowPos, riverPos, riverSlopePos, lakePos, coastPos};
317  array<float> valuesCam = {seaCam, forestCam, cityCam, meadowCam, riverCam, riverSlopeCam, lakeCam, coastCam};
318 
319  // We want to work with higher number
320  for (int i; i < 8; i++)
321  {
322  if (valuesCam[i] > valuesPos[i])
323  valuesPos[i] = valuesCam[i];
324  }
325 
326  // Get maximum
327  float v = valuesPos[0];
328  int idx;
329  int i = 1;
330  for (i; i < 8; i++)
331  {
332  if (valuesPos[i] >= v)
333  {
334  v = valuesPos[i];
335  idx = i;
336  }
337  }
338 
339  // Check for fresh water
340  if (idx == 0)
341  {
342  worldPos[1] = 0;
343  }
344  else
345  {
346  float surfaceHeight = world.GetSurfaceY(worldPos[0], worldPos[2]);
347  worldPos[1] = surfaceHeight;
348  }
349 
350  EWaterSurfaceType waterSurfaceType;
351  float lakeArea;
352  //Sometimes other biomes overlap and we want to prioritise water
353  if (valuesPos[6] >= 0.75)
354  {
355  idx = 6;
356  worldPos[1] = SCR_WorldTools.GetWaterSurfaceY(world, worldPos, waterSurfaceType, lakeArea);
357  }
358 
359  return idx;
360  }
361 
362  //------------------------------------------------------------------------------------------------
364  protected void UpdateDensity()
365  {
366  m_aDensity.Clear();
367  m_aDensity.Resize(m_aSpawnDef.Count());
368  foreach (SCR_InsectParticle particle : m_aParticles)
369  {
370  m_aDensity[particle.m_iSoundGroup] = m_aDensity[particle.m_iSoundGroup] + m_aSpawnDef[particle.m_iSoundGroup].m_iDensityConsumption;
371  }
372  }
373 
374  //------------------------------------------------------------------------------------------------
376  protected void LoadConfigs()
377  {
378  foreach (SCR_RandomPositionalInsectsDef def : m_aRandomPositionalInsectsDef)
379  {
380  SCR_InsectGroup insectGroup;
381  if (def.m_sInsectGroup != string.Empty)
382  {
383  Resource holder = BaseContainerTools.LoadContainer(def.m_sInsectGroup);
384  if (holder)
385  insectGroup = SCR_InsectGroup.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
386  }
387 
388  if (!insectGroup)
389  {
390  Print("AMBIENT LIFE: SCR_AmbientInsectsComponent: Missing Ambience Sound Gropu Config", LogLevel.WARNING);
391  m_AmbientInsectsComponent.RemoveInsectEffect(this);
392 
393  return;
394  }
395 
396  m_aInsectGroup.Insert(insectGroup);
397 
398  // ---
399  SCR_InsectSpawnDef spawnDef;
400  if (def.m_sSpawnDef != string.Empty)
401  {
402  Resource holder = BaseContainerTools.LoadContainer(def.m_sSpawnDef);
403  if (holder)
404  spawnDef = SCR_InsectSpawnDef.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
405  }
406 
407  if (!spawnDef)
408  {
409  Print("AMBIENT LIFE: SCR_AmbientInsectsComponent: Missing Spawn Definition Config", LogLevel.WARNING);
410  m_AmbientInsectsComponent.RemoveInsectEffect(this);
411 
412  return;
413  }
414 
415  m_aSpawnDef.Insert(spawnDef);
416  }
417 
418  // ---
419  SCR_DayTimeCurveDefConfig ambientSoundsDayTimeCurveDefinitionConfig;
420  if (m_sDayTimeCurve != string.Empty)
421  {
422  Resource holder = BaseContainerTools.LoadContainer(m_sDayTimeCurve);
423  if (holder)
424  ambientSoundsDayTimeCurveDefinitionConfig = SCR_DayTimeCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
425  }
426 
427  if (!ambientSoundsDayTimeCurveDefinitionConfig)
428  {
429  Print("AMBIENT LIFE: SCR_AmbientInsectsComponent: Missing Daytime Curve Deffinition Config", LogLevel.WARNING);
430  m_AmbientInsectsComponent.RemoveInsectEffect(this);
431 
432  return;
433  }
434 
435  m_aDayTimeCurve = ambientSoundsDayTimeCurveDefinitionConfig.m_aDayTimeCurve;
436 
437  // ---
438  SCR_WindCurveDefConfig ambientSoundsWindDefinitionConfig;
439  if (m_sWindCurve != string.Empty)
440  {
441  Resource holder = BaseContainerTools.LoadContainer(m_sWindCurve);
442  if (holder)
443  ambientSoundsWindDefinitionConfig = SCR_WindCurveDefConfig.Cast(BaseContainerTools.CreateInstanceFromContainer(holder.GetResource().ToBaseContainer()));
444  }
445 
446  if (!ambientSoundsWindDefinitionConfig)
447  {
448  Print("AMBIENT LIFE: SCR_AmbientInsectsComponent: Missing Wind Curve Definition Config", LogLevel.WARNING);
449  m_AmbientInsectsComponent.RemoveInsectEffect(this);
450 
451  return;
452  }
453 
454  m_aWindModifier = ambientSoundsWindDefinitionConfig.m_aWindModifier;
455  }
456 
457  //------------------------------------------------------------------------------------------------
458  // Called by SCR_AmbientSoundComponent in OnPostInit()
459  override void OnPostInit(SCR_AmbientSoundsComponent ambientSoundsComponent, SCR_AmbientInsectsComponent ambientInsectsComponent, SignalsManagerComponent signalsManagerComponent)
460  {
461  super.OnPostInit(ambientSoundsComponent, ambientInsectsComponent, signalsManagerComponent);
462 
463  LoadConfigs();
464 
465  int count = m_aSpawnDef.Count();
466  m_aDensity.Resize(count);
467  m_aAngleOffset.Resize(count);
468  m_aDensityModifier.Resize(count);
469  }
470 }
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_AmbientInsectsComponent
Definition: SCR_AmbientInsectsComponent.c:18
SCR_InsectGroup
Definition: SCR_InsectGroup.c:2
SCR_InsectParticle
Definition: SCR_InsectParticle.c:2
WIND_CURVE_COUNT
const int WIND_CURVE_COUNT
Definition: SCR_WindCurveDef.c:2
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
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_WorldTools
Definition: SCR_WorldTools.c:1
SCR_RandomPositionalInsects
Spawns Insect particles around camera based on define behaviour.
Definition: SCR_RandomPositionalInsects.c:3
SCR_DayTimeCurveDefConfig
Array size has to have the same count as EDayTimeCurve.
Definition: SCR_DayTimeCurveDefConfig.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
SCR_RandomPositionalInsectsDef
Definition: SCR_RandomPositionalInsectsDef.c:2
DAY_TIME_CURVE_COUNT
const int DAY_TIME_CURVE_COUNT
Definition: SCR_DayTimeCurveDef.c:1
SCR_InsectDef
Definition: SCR_InsectDef.c:2
SCR_AmbientSoundsComponent
Definition: SCR_AmbientSoundsComponent.c:17
SCR_InsectSpawnDef
Definition: SCR_InsectSpawnDef.c:2
SCR_InsectType
Definition: SCR_InsectType.c:2
SCR_AmbientInsectsEffect
Definition: SCR_AmbientInsectEffect.c:2
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
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
EWaterSurfaceType
EWaterSurfaceType
Definition: EWaterSurfaceType.c:7
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
m_aParticles
protected ref array< ref SCR_InsectParticle > m_aParticles
Definition: SCR_PositionalInsectType.c:19