Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_MotorExhaustEffectGeneralComponent.c
Go to the documentation of this file.
1 [ComponentEditorProps(icon: HYBRID_COMPONENT_ICON)]
3 {
4 }
5 
6 class SCR_MotorExhaustEffectGeneralComponent : MotorExhaustEffectComponent
7 {
8  protected Particles m_ExhaustParticles;
9  protected ParticleEffectEntity m_ExhaustEmitter;
10  protected ParticleEffectEntity m_DamagedEmitter;
12  protected SignalsManagerComponent m_SignalsManager;
13  protected float m_fRPMScaled; // 0 to 1 scale of RPM between current and max RPM
14  protected float m_fRPMScaledOld; // RPM scale in previous frame to calculate acceleration
15  protected float m_fThrust; // 0 to 1. Represents how much pedal to the metal is the driver pushing.
16  protected float m_fEngineLoad; // How much load is the engine being pushed through
17  protected float m_fPreviousLoad = -1; // Previous load state to detect necessary change
18  protected float m_fLifetimeScale; // Lifetime of the exhaust particles
19  protected int m_iIsExhaustUnderWaterSignalIdx; // IsExhaustUnderWater signal index
20  protected int m_iEngineLoadIdx; // engine load singal index
21  protected bool m_bIsUnderwater;
22  protected bool m_bIsDefective;
23 
24  // There are some heavy calculations with particles going on per frame. The following variables solve the performance impact by calling them less often when they happen far away from the camera.
25  protected float m_fUpdateDelay; // Desired delay between each particle calculations in seconds. 0 means per frame.
26  protected float m_fCurrentUpdateDelay; // The time of current delay
27  protected const float TICK_TIME_DELAY_MAX = 2; // Max acceptable delay in seconds
28  protected const float TICK_DELAY_RANGE_START = 15; // Starting range at which the delay begins to increase (from 0 to TICK_TIME_DELAY_MAX)
29  protected const float TICK_DELAY_RANGE_END = 100; // End range at which delay reaches its maximum (TICK_TIME_DELAY_MAX)
30 
31  // Arrays of arrays of emitter indices (one array of indices per stage).
32  // E.g. m_aExhaustStageEmitters[1][0] gets emitter index of the emitter #0 of stage #1
33  protected ref array<ref array<int>> m_aExhaustStagesEmitters;
34  protected ref array<ref array<int>> m_aDamageStagesEmitters;
35 
36  protected float m_fStartupTimeLeft; // Remaining time to keep playing the startup particle effect after startup
37 
38  [Attribute("{AEA751F0BE7FE821}Particles/Vehicle/Vehicle_smoke_car_exhaust_damage.ptc", UIWidgets.ResourceNamePicker, desc: "Particle effect for damaged engine", params: "ptc")]
39  protected ResourceName m_sDamagedParticle;
40 
41  [Attribute("1", UIWidgets.Auto, desc: "Time to play damaged exhaust particle after startup")]
42  protected float m_fStartupTime;
43 
44  //------------------------------------------------------------------------------------------------
45  override void OnInit(IEntity owner)
46  {
47  if (System.IsConsoleApp())
48  {
49  Deactivate(owner);
50  return;
51  }
52 
54  m_SignalsManager = SignalsManagerComponent.Cast(owner.FindComponent(SignalsManagerComponent));
55 
56  if (m_SignalsManager)
57  {
58  m_iIsExhaustUnderWaterSignalIdx = m_SignalsManager.AddOrFindSignal("IsExhaustUnderWater");
59  m_iEngineLoadIdx = m_SignalsManager.AddOrFindSignal("engineLoad");
60  }
61  }
62 
63  //------------------------------------------------------------------------------------------------
64  override void OnDelete(IEntity owner)
65  {
67 
68  super.OnDelete(owner);
69  }
70 
71  //------------------------------------------------------------------------------------------------
72  // Parses an emitter name and returns index of a stage the emitter belongs to.
73  // Returns -1 if the emitter's name does not meet the stage naming WeatherWindPattern
74  // (s<X>_<name> where <X> is a number of a stage and <name> is any string, e.g. s0_smoke, s1_smoke, s10_debris etc.)
75  protected static int GetStageIndex(string emitterName)
76  {
77  static const string EMITTER_STAGE_PREFIX = "s";
78  static const string EMITTER_STAGE_SUFIX = "_";
79 
80  int offset = EMITTER_STAGE_PREFIX.Length();
81  if (!emitterName.StartsWith(EMITTER_STAGE_PREFIX) || !emitterName.IsDigitAt(offset))
82  return -1;
83 
84  int numberLen;
85  int stageNo = emitterName.ToInt(offset: offset, parsed: numberLen);
86  offset += numberLen;
87  if (!emitterName.ContainsAt(EMITTER_STAGE_SUFIX, offset))
88  return -1;
89 
90  return stageNo;
91  }
92 
93  //------------------------------------------------------------------------------------------------
94  // Creates an index of emitters in stages of Particles of ParticleEffectEntity,
95  // i.e. array of arrays of emitter indices - one array of emitter indices for each stage.
96  // E.g. for stageEmitters = CreateStageIndex(effectEntity),
97  // at stageEmitters[2] there is a an array of indices of emitters belonging to the the stage #2.
98  protected static array<ref array<int>> CreateStageIndexes(notnull ParticleEffectEntity effectEntity)
99  {
100  Particles particles = effectEntity.GetParticles();
101  if (!particles)
102  return {};
103 
104  array<ref array<int>> ret = {{}};
105 
106  array<string> emitterNames = {};
107  int emitterNamesCount = particles.GetEmitterNames(emitterNames);
108 
109  for (int i; i < emitterNamesCount; i++)
110  {
111  int stage = GetStageIndex(emitterNames[i]);
112  if (stage < 0)
113  continue;
114 
115  if (stage >= ret.Count())
116  ret.Resize(stage + 1);
117 
118  if (!ret[stage])
119  ret[stage] = {};
120 
121  ret[stage].Insert(i);
122  }
123 
124  return ret;
125  }
126 
127  //------------------------------------------------------------------------------------------------
128  void Update(float timeSlice)
129  {
130  // Check if delay treshold was crossed. This prevents calling intense calculations per frame for vehicles which are far away from camera as they have low priority
131  m_fCurrentUpdateDelay += timeSlice;
133  return;
134 
136 
137  // Check if effect exists. If not then try to get it.
138  if (!m_ExhaustEmitter)
139  m_ExhaustEmitter = ParticleEffectEntity.Cast(GetParticleEntity());
140 
141  if (!m_ExhaustEmitter)
142  return;
143 
144  // Check if exhaust is underwater
145  bool isUnderwater = SCR_WorldTools.IsObjectUnderwater(m_ExhaustEmitter);
146  if (m_bIsUnderwater != isUnderwater)
147  {
148  m_bIsUnderwater = isUnderwater;
149  m_SignalsManager.SetSignalValue(m_iIsExhaustUnderWaterSignalIdx, isUnderwater);
150  }
151 
152  // Check if engine is damaged
153  m_bIsDefective = !isUnderwater && m_DamageManager && m_DamageManager.GetEngineEfficiency() <= m_DamageManager.GetEngineMalfunctionThreshold();
154 
155  // Update emitters
156  UpdateExhaustEmitter(timeSlice);
157 
159  UpdateDamagedEmitter(timeSlice);
160 
161  // Calculate distance between owner and camera
162  CameraBase camera = GetGame().GetCameraManager().CurrentCamera();
163  if (!camera)
164  return;
165 
166  float distance = vector.Distance(camera.GetOrigin(), m_ExhaustEmitter.GetOrigin());
167 
168  // Prolong update interval based on the distance between camera and effect
171  else
172  m_fUpdateDelay = 0;
173  }
174 
175  //------------------------------------------------------------------------------------------------
176  protected void UpdateExhaustParticles(float timeSlice)
177  {
178  // We are about to call relatively performance heavy update of particle in OnUpdateEffect(...). This will be done per frame but only if the effect is very close to camera. Otherwise the update will be separated by time intervals to save performance.
180  if (m_fRPMScaled > 0 || m_fPreviousLoad < 0)
181  {
182  // Prepare values which will be used for particle calculations later in OnUpdateEffect(...)
184  float RPM_acceleration = (m_fRPMScaled - m_fRPMScaledOld) * 1000 * timeSlice;
186  }
187 
188  // Startup force full engine load
189  if (m_fStartupTimeLeft > 0)
190  m_fEngineLoad = 1;
191  else if (m_SignalsManager)
192  m_fEngineLoad = Math.Max(m_SignalsManager.GetSignalValue(m_iEngineLoadIdx), 0);
193 
194  if (float.AlmostEqual(m_fEngineLoad, m_fPreviousLoad))
195  return;
196 
198 
199  // Update exhaust stages
201  m_aExhaustStagesEmitters = CreateStageIndexes(m_ExhaustEmitter);
202 
204  }
205 
206  //------------------------------------------------------------------------------------------------
208  protected void UpdateExhaustEmitter(float timeSlice)
209  {
210  bool shouldBePlaying = !m_bIsUnderwater && !(m_bIsDefective && m_DamagedEmitter);
211  bool isPlaying = m_ExhaustEmitter && m_ExhaustEmitter.GetState() == EParticleEffectState.PLAYING;
212 
213  // Enable only if no damage particles are being played
214  if (shouldBePlaying)
215  {
216  if (!isPlaying)
217  m_ExhaustEmitter.Play();
218 
219  UpdateExhaustParticles(timeSlice);
220  }
221  else
222  {
223  // Pause so that emitter does not get deleted until engine is stopped
224  if (isPlaying)
225  m_ExhaustEmitter.Pause();
226  }
227  }
228 
229  //------------------------------------------------------------------------------------------------
231  protected void UpdateDamagedEmitter(float timeSlice)
232  {
233  bool isEmitting = m_DamagedEmitter && m_DamagedEmitter.GetState() == EParticleEffectState.PLAYING;
234  if (m_bIsDefective == isEmitting)
235  return;
236 
237  if (m_bIsDefective)
238  {
239  if (m_DamagedEmitter)
240  m_DamagedEmitter.Play();
241  else if (!m_sDamagedParticle.IsEmpty())
243  }
244  else
245  {
246  if (m_DamagedEmitter)
247  m_DamagedEmitter.StopEmission();
248  }
249  }
250 
251  //------------------------------------------------------------------------------------------------
253  protected void CreateDamageEffect()
254  {
255  ParticleEffectEntitySpawnParams spawnParams();
256 
257  EntitySlotInfo effectPosition = GetEffectPosition();
258  if (effectPosition)
259  {
260  spawnParams.PivotID = effectPosition.GetNodeId();
261  effectPosition.GetLocalTransform(spawnParams.Transform);
262  }
263 
264  spawnParams.UseFrameEvent = true;
265  spawnParams.Parent = GetOwner();
266 
267  m_DamagedEmitter = ParticleEffectEntity.SpawnParticleEffect(m_sDamagedParticle, spawnParams);
268  }
269 
270  //------------------------------------------------------------------------------------------------
271  protected void AdjustEngineEffects(notnull ParticleEffectEntity effectEntity, array<ref array<int>> stageIndexes)
272  {
273  Particles particles = effectEntity.GetParticles();
274  if (!particles)
275  return;
276 
277  if (stageIndexes && !stageIndexes.IsEmpty()) // Check if the assigned particle effect supports staging (Staging divides effect's emittors into groups which are selectively enabled/disabled according to our needs)
278  {
279  // Staging is supported, so disable all emittors...
280  particles.SetParam(-1, EmitterParam.BIRTH_RATE, 0);
281  particles.SetParam(-1, EmitterParam.BIRTH_RATE_RND, 0);
282 
283  // ... now enable only the relevant emittors and work with them
284  int iMaxStage = stageIndexes.Count();
285  int stage = Math.ClampInt(Math.Ceil(iMaxStage * m_fEngineLoad), 1, iMaxStage) - 1;
286  array<int> stageEmitterIDs = stageIndexes[stage];
287 
288  // Now we work only with the relevant stage (group) of emitters
289  for (int i; i < stageEmitterIDs.Count(); i++)
290  {
291  particles.MultParam(stageEmitterIDs[i], EmitterParam.BIRTH_RATE, m_fRPMScaled* 0.5 + 0.5);
292  particles.MultParam(stageEmitterIDs[i], EmitterParam.BIRTH_RATE_RND, m_fRPMScaled* 0.5 + 0.5);
293  particles.MultParam(stageEmitterIDs[i], EmitterParam.VELOCITY, (m_fRPMScaled* 3));
294  particles.MultParam(stageEmitterIDs[i], EmitterParam.VELOCITY_RND, (m_fRPMScaled* 3));
295  particles.MultParam(stageEmitterIDs[i], EmitterParam.AIR_RESISTANCE, m_fRPMScaled);
296  particles.MultParam(stageEmitterIDs[i], EmitterParam.AIR_RESISTANCE_RND, m_fRPMScaled);
297  }
298  }
299  else
300  {
301  // Staging is not supported so apply changes to all emittors.
302  particles.MultParam(-1, EmitterParam.BIRTH_RATE, m_fRPMScaled* 1);
303  particles.MultParam(-1, EmitterParam.BIRTH_RATE_RND, m_fRPMScaled* 1);
304  particles.MultParam(-1, EmitterParam.LIFETIME, m_fLifetimeScale);
305  particles.MultParam(-1, EmitterParam.LIFETIME_RND, m_fLifetimeScale);
306  particles.MultParam(-1, EmitterParam.VELOCITY, (m_fRPMScaled* 7));
307  particles.MultParam(-1, EmitterParam.VELOCITY_RND, (m_fRPMScaled* 7));
308  particles.MultParam(-1, EmitterParam.AIR_RESISTANCE, m_fRPMScaled);
309  particles.MultParam(-1, EmitterParam.AIR_RESISTANCE_RND, m_fRPMScaled);
310  }
311  }
312 
313  //------------------------------------------------------------------------------------------------
315  void OnEngineStart(bool startup)
316  {
318  m_fPreviousLoad = -1;
319  m_bIsUnderwater = false;
320 
321  if (startup)
323  else
324  m_fStartupTimeLeft = 0;
325 
326  TurnOn(GetOwner());
328  }
329 
330  //------------------------------------------------------------------------------------------------
333  {
334  TurnOff();
336 
337  if (m_DamagedEmitter)
338  m_DamagedEmitter.StopEmission();
339  }
340 
341  //------------------------------------------------------------------------------------------------
343  {
344  World world = GetOwner().GetWorld();
345  MotorExhaustSystem updateSystem = MotorExhaustSystem.Cast(world.FindSystem(MotorExhaustSystem));
346  if (!updateSystem)
347  return;
348 
349  updateSystem.Register(this);
350  }
351 
352  //------------------------------------------------------------------------------------------------
354  {
355  World world = GetOwner().GetWorld();
356  MotorExhaustSystem updateSystem = MotorExhaustSystem.Cast(world.FindSystem(MotorExhaustSystem));
357  if (!updateSystem)
358  return;
359 
360  updateSystem.Unregister(this);
361  }
362 }
m_fUpdateDelay
protected float m_fUpdateDelay
Definition: SCR_MotorExhaustEffectGeneralComponent.c:25
ComponentEditorProps
SCR_FragmentEntityClass ComponentEditorProps
m_fPreviousLoad
protected float m_fPreviousLoad
Definition: SCR_MotorExhaustEffectGeneralComponent.c:17
m_sDamagedParticle
protected ResourceName m_sDamagedParticle
Definition: SCR_MotorExhaustEffectGeneralComponent.c:39
m_aExhaustStagesEmitters
protected ref array< ref array< int > > m_aExhaustStagesEmitters
Definition: SCR_MotorExhaustEffectGeneralComponent.c:33
m_aDamageStagesEmitters
protected ref array< ref array< int > > m_aDamageStagesEmitters
Definition: SCR_MotorExhaustEffectGeneralComponent.c:34
m_ExhaustEmitter
protected ParticleEffectEntity m_ExhaustEmitter
Definition: SCR_MotorExhaustEffectGeneralComponent.c:9
MotorExhaustSystem
Definition: MotorExhaustSystem.c:1
OnEngineStop
void OnEngineStop()
Turn off the effect and pause the damaged exhaust effect.
Definition: SCR_MotorExhaustEffectGeneralComponent.c:332
m_fStartupTime
protected float m_fStartupTime
Definition: SCR_MotorExhaustEffectGeneralComponent.c:42
TICK_TIME_DELAY_MAX
const protected float TICK_TIME_DELAY_MAX
Definition: SCR_MotorExhaustEffectGeneralComponent.c:27
TurnOff
void TurnOff()
Remove every particle associed with this effect.
Definition: SCR_FireplaceComponent.c:91
GetEffectPosition
proto external EntitySlotInfo GetEffectPosition()
MotorExhaustEffectComponentClass
Definition: MotorExhaustEffectComponent.c:12
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
m_fRPMScaled
protected float m_fRPMScaled
Definition: SCR_MotorExhaustEffectGeneralComponent.c:13
OnDelete
override void OnDelete(IEntity owner)
Definition: SCR_MotorExhaustEffectGeneralComponent.c:64
GetSignalThrust
proto external float GetSignalThrust()
SCR_VehicleDamageManagerComponent
void SCR_VehicleDamageManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_VehicleDamageManagerComponent.c:1720
TurnOn
void TurnOn()
Definition: SCR_FireplaceComponent.c:61
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
m_iIsExhaustUnderWaterSignalIdx
protected int m_iIsExhaustUnderWaterSignalIdx
Definition: SCR_MotorExhaustEffectGeneralComponent.c:19
SCR_WorldTools
Definition: SCR_WorldTools.c:1
m_ExhaustParticles
SCR_MotorExhaustEffectGeneralComponentClass m_ExhaustParticles
AdjustEngineEffects
protected void AdjustEngineEffects(notnull ParticleEffectEntity effectEntity, array< ref array< int >> stageIndexes)
Definition: SCR_MotorExhaustEffectGeneralComponent.c:271
m_fStartupTimeLeft
protected float m_fStartupTimeLeft
Definition: SCR_MotorExhaustEffectGeneralComponent.c:36
UpdateDamagedEmitter
protected void UpdateDamagedEmitter(float timeSlice)
Damaged engine exhaust.
Definition: SCR_MotorExhaustEffectGeneralComponent.c:231
TICK_DELAY_RANGE_START
const protected float TICK_DELAY_RANGE_START
Definition: SCR_MotorExhaustEffectGeneralComponent.c:28
EntitySlotInfo
Adds ability to attach an object to a slot.
Definition: EntitySlotInfo.c:8
OnEngineStart
void OnEngineStart(bool startup)
Turn on the effect for engine start and reset flow variables.
Definition: SCR_MotorExhaustEffectGeneralComponent.c:315
m_fThrust
protected float m_fThrust
Definition: SCR_MotorExhaustEffectGeneralComponent.c:15
Attribute
typedef Attribute
Post-process effect of scripted camera.
distance
float distance
Definition: SCR_DestructibleTreeV2.c:29
UpdateExhaustParticles
protected void UpdateExhaustParticles(float timeSlice)
Definition: SCR_MotorExhaustEffectGeneralComponent.c:176
ConnectToMotorExhaustSystem
protected void ConnectToMotorExhaustSystem()
Definition: SCR_MotorExhaustEffectGeneralComponent.c:342
Update
void Update(float timeSlice)
Definition: SCR_MotorExhaustEffectGeneralComponent.c:128
m_bIsDefective
protected bool m_bIsDefective
Definition: SCR_MotorExhaustEffectGeneralComponent.c:22
m_DamageManager
protected SCR_VehicleDamageManagerComponent m_DamageManager
Definition: SCR_MotorExhaustEffectGeneralComponent.c:11
m_fRPMScaledOld
protected float m_fRPMScaledOld
Definition: SCR_MotorExhaustEffectGeneralComponent.c:14
m_bIsUnderwater
protected bool m_bIsUnderwater
Definition: SCR_MotorExhaustEffectGeneralComponent.c:21
TICK_DELAY_RANGE_END
const protected float TICK_DELAY_RANGE_END
Definition: SCR_MotorExhaustEffectGeneralComponent.c:29
SCR_MotorExhaustEffectGeneralComponentClass
Definition: SCR_MotorExhaustEffectGeneralComponent.c:2
DisconnectFromMotorExhaustSystem
protected void DisconnectFromMotorExhaustSystem()
Definition: SCR_MotorExhaustEffectGeneralComponent.c:353
Deactivate
protected void Deactivate()
Definition: SCR_BaseHintCondition.c:27
m_iEngineLoadIdx
protected int m_iEngineLoadIdx
Definition: SCR_MotorExhaustEffectGeneralComponent.c:20
UpdateExhaustEmitter
protected void UpdateExhaustEmitter(float timeSlice)
Ignition engine exhaust.
Definition: SCR_MotorExhaustEffectGeneralComponent.c:208
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
m_fLifetimeScale
protected float m_fLifetimeScale
Definition: SCR_MotorExhaustEffectGeneralComponent.c:18
CreateDamageEffect
protected void CreateDamageEffect()
Create damaged exhaust particles.
Definition: SCR_MotorExhaustEffectGeneralComponent.c:253
m_fCurrentUpdateDelay
protected float m_fCurrentUpdateDelay
Definition: SCR_MotorExhaustEffectGeneralComponent.c:26
GetParticleEntity
BaseEffectComponentClass GameComponentClass GetParticleEntity()
Returns the particle entity associated with this effect component.
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
m_fEngineLoad
protected float m_fEngineLoad
Definition: SCR_MotorExhaustEffectGeneralComponent.c:16
GetRpmScaled
proto external float GetRpmScaled()
m_SignalsManager
protected SignalsManagerComponent m_SignalsManager
Definition: SCR_MotorExhaustEffectGeneralComponent.c:12
OnInit
override void OnInit(IEntity owner)
Definition: SCR_MotorExhaustEffectGeneralComponent.c:45
m_DamagedEmitter
protected ParticleEffectEntity m_DamagedEmitter
Definition: SCR_MotorExhaustEffectGeneralComponent.c:10