Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_AmbientVehicleSystem.c
Go to the documentation of this file.
1 void OnAmbientVehicleSpawnedDelegate(SCR_AmbientVehicleSpawnPointComponent spawnpoint, Vehicle vehicle);
2 
4 
5 typedef ScriptInvokerBase<OnAmbientVehicleSpawnedDelegate> OnAmbientVehicleSpawnedInvoker;
6 
7 //------------------------------------------------------------------------------------------------
9 {
10  protected static const int CHECK_INTERVAL = 3; //s, how often should an individual spawnpoint be checked
11  protected static const int DESPAWN_TIMEOUT = 10000; //ms
12  protected static const int PARKED_THRESHOLD = 5; //m, how far away can the spawned vehicle moved before being considered used
13 
14  protected static const int SPAWN_RADIUS_MIN_SQ = 500 * 500; // Square value for distance checks
15  protected static const int SPAWN_RADIUS_MAX_SQ = 1000 * 1000; // Square value for distance checks
16  protected static const int DESPAWN_RADIUS_DIFF_SQ = 200 * 200; // Square value for distance checks
17 
18  protected ref array<SCR_AmbientVehicleSpawnPointComponent> m_aSpawnpoints = {};
19  protected ref array<IEntity> m_aPlayers = {};
20 
21  protected ref OnAmbientVehicleSpawnedInvoker m_OnVehicleSpawned;
22 
23  protected int m_iLastAssignedIndex;
24  protected int m_iIndexToCheck;
25  protected int m_iSpawnDistanceSq;
26  protected int m_iDespawnDistanceSq;
27 
28  protected float m_fTimer;
29  protected float m_fCheckInterval;
30 
31  //------------------------------------------------------------------------------------------------
32  override event protected void OnInit()
33  {
34  // No need to run updates unless some spawnpoints are actually registered
35  if (m_aSpawnpoints.IsEmpty())
36  Enable(false);
37 
38  RefreshPlayerList();
39 
40  // Calculate (de)spawn distance based on view distance, have it squared for faster distance calculation
41  int fractionVD = GetGame().GetViewDistance() * 0.3;
42  m_iSpawnDistanceSq = fractionVD * fractionVD;
43  m_iSpawnDistanceSq = Math.Min(SPAWN_RADIUS_MAX_SQ, m_iSpawnDistanceSq);
44  m_iSpawnDistanceSq = Math.Max(SPAWN_RADIUS_MIN_SQ, m_iSpawnDistanceSq);
45  m_iDespawnDistanceSq = m_iSpawnDistanceSq + DESPAWN_RADIUS_DIFF_SQ;
46 
48 
49  if (!gameMode)
50  return;
51 
52  gameMode.GetOnPlayerSpawned().Insert(OnPlayerSpawnedOrDeleted);
53  gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
54  gameMode.GetOnPlayerDeleted().Insert(OnPlayerSpawnedOrDeleted);
55  gameMode.GetOnPlayerDisconnected().Insert(OnPlayerDisconnected);
56  }
57 
58  //------------------------------------------------------------------------------------------------
59  override event protected void OnCleanup()
60  {
62 
63  if (!gameMode)
64  return;
65 
66  gameMode.GetOnPlayerSpawned().Remove(OnPlayerSpawnedOrDeleted);
67  gameMode.GetOnPlayerKilled().Remove(OnPlayerKilled);
68  gameMode.GetOnPlayerDeleted().Remove(OnPlayerSpawnedOrDeleted);
69  gameMode.GetOnPlayerDisconnected().Remove(OnPlayerDisconnected);
70  }
71 
72  //------------------------------------------------------------------------------------------------
73  override event protected void OnUpdate(ESystemPoint point)
74  {
75  if (!GetGame().AreGameFlagsSet(EGameFlags.SpawnVehicles))
76  {
77  Enable(false);
78  return;
79  }
80 
81  float timeSlice = GetWorld().GetFixedTimeSlice();
82 
83  m_fTimer += timeSlice;
84 
85  if (m_fTimer < m_fCheckInterval)
86  return;
87 
88  m_fTimer = 0;
89 
90  ProcessSpawnpoint(m_iIndexToCheck);
91  m_iIndexToCheck++;
92 
93  if (!m_aSpawnpoints.IsIndexValid(m_iIndexToCheck))
94  m_iIndexToCheck = 0;
95  }
96 
97  //------------------------------------------------------------------------------------------------
98  override event bool ShouldBePaused()
99  {
100  return true;
101  }
102 
103  //------------------------------------------------------------------------------------------------
104  static SCR_AmbientVehicleSystem GetInstance()
105  {
106  World world = GetGame().GetWorld();
107 
108  if (!world)
109  return null;
110 
111  return SCR_AmbientVehicleSystem.Cast(world.FindSystem(SCR_AmbientVehicleSystem));
112  }
113 
114  //------------------------------------------------------------------------------------------------
115  OnAmbientVehicleSpawnedInvoker GetOnVehicleSpawned()
116  {
117  if (!m_OnVehicleSpawned)
118  m_OnVehicleSpawned = new OnAmbientVehicleSpawnedInvoker();
119 
120  return m_OnVehicleSpawned;
121  }
122 
123  //------------------------------------------------------------------------------------------------
124  protected void UpdateCheckInterval()
125  {
126  m_fCheckInterval = CHECK_INTERVAL / m_aSpawnpoints.Count();
127  }
128 
129  //------------------------------------------------------------------------------------------------
130  protected void RefreshPlayerList()
131  {
132  m_aPlayers.Clear();
133  array<int> playerIds = {};
134  PlayerManager pc = GetGame().GetPlayerManager();
135  int playersCount = pc.GetPlayers(playerIds);
136 
137  foreach (int playerId : playerIds)
138  {
139  IEntity player = pc.GetPlayerControlledEntity(playerId);
140 
141  if (!player)
142  continue;
143 
144  CharacterControllerComponent comp = CharacterControllerComponent.Cast(player.FindComponent(CharacterControllerComponent));
145 
146  if (!comp || comp.IsDead())
147  continue;
148 
149  m_aPlayers.Insert(player);
150  }
151  }
152 
153  //------------------------------------------------------------------------------------------------
154  protected void OnPlayerSpawnedOrDeleted(int playerId, IEntity player)
155  {
156  RefreshPlayerList();
157  }
158 
159  //------------------------------------------------------------------------------------------------
160  protected void ProcessSpawnpoint(int spawnpointIndex)
161  {
162  SCR_AmbientVehicleSpawnPointComponent spawnpoint = m_aSpawnpoints[spawnpointIndex];
163 
164  if (!spawnpoint || spawnpoint.GetIsDepleted())
165  return;
166 
167  Vehicle spawnedVeh = spawnpoint.GetSpawnedVehicle();
168  ChimeraWorld world = GetWorld();
169  WorldTimestamp currentTime = world.GetServerTimestamp();
170  int respawnPeriod = spawnpoint.GetRespawnPeriod();
171 
172  // Non-respawning vehicle has beed deleted by other means
173  // Ignore this spawnpoint from now on
174  if (!spawnedVeh && spawnpoint.GetIsSpawnProcessed() && respawnPeriod <= 0)
175  {
176  spawnpoint.SetIsDepleted(true);
177  return;
178  }
179 
180  if (!spawnedVeh)
181  {
182  WorldTimestamp respawnTimestamp = spawnpoint.GetRespawnTimestamp();
183 
184  // Respawn timer is ticking
185  if (respawnTimestamp.Greater(currentTime))
186  return;
187 
188  if (spawnpoint.GetIsFirstSpawnDone())
189  {
190  // Vehicle has been deleted, setup respawn timer if enabled
191  if (respawnTimestamp == 0 && respawnPeriod > 0)
192  {
193  spawnpoint.SetRespawnTimestamp(currentTime.PlusSeconds(respawnPeriod));
194  return;
195  }
196  }
197  }
198 
199  vector location = spawnpoint.GetOwner().GetOrigin();
200 
201  // Only handle vehicles which are still on their spawnpoints
202  if (spawnedVeh && vector.DistanceXZ(spawnedVeh.GetOrigin(), location) > PARKED_THRESHOLD)
203  {
204  // Non-respawning spawnpoints get depleted once the vehicle leaves the spawnpoint
205  if (spawnpoint.GetRespawnPeriod() <= 0)
206  spawnpoint.SetIsDepleted(true);
207 
208  return;
209  }
210 
211  bool playersNear = false;
212  bool playersFar = true;
213  int distance;
214 
215  // Define if any player is close enough to spawn or if all players are far enough to despawn
216  foreach (IEntity player : m_aPlayers)
217  {
218  if (!player)
219  continue;
220 
221  distance = vector.DistanceSq(player.GetOrigin(), location);
222 
223  if (distance < m_iDespawnDistanceSq)
224  {
225  playersFar = false;
226 
227  if (distance < m_iSpawnDistanceSq)
228  {
229  playersNear = true;
230  break;
231  }
232  }
233  }
234 
235  if (!spawnedVeh && playersNear)
236  {
237  Vehicle vehicle = spawnpoint.SpawnVehicle();
238 
239  if (vehicle && m_OnVehicleSpawned)
240  m_OnVehicleSpawned.Invoke(spawnpoint, vehicle);
241 
242  return;
243  }
244 
245  // Delay is used so dying players don't see the despawn happen
246  if (spawnedVeh && playersFar)
247  {
248  WorldTimestamp despawnT = spawnpoint.GetDespawnTimer();
249 
250  if (despawnT == 0)
251  spawnpoint.SetDespawnTimer(currentTime.PlusMilliseconds(DESPAWN_TIMEOUT));
252  else if (currentTime.Greater(despawnT))
253  spawnpoint.DespawnVehicle();
254  }
255  else
256  {
257  spawnpoint.SetDespawnTimer(null);
258  }
259  }
260 
261  //------------------------------------------------------------------------------------------------
262  void RegisterSpawnpoint(notnull SCR_AmbientVehicleSpawnPointComponent spawnpoint)
263  {
264  if (!IsEnabled())
265  Enable(true);
266 
267  m_aSpawnpoints.Insert(spawnpoint);
268  spawnpoint.SetID(m_iLastAssignedIndex);
269  m_iLastAssignedIndex++;
270  UpdateCheckInterval();
271  }
272 
273  //------------------------------------------------------------------------------------------------
274  void UnregisterSpawnpoint(notnull SCR_AmbientVehicleSpawnPointComponent spawnpoint)
275  {
276  m_aSpawnpoints.RemoveItem(spawnpoint);
277  m_iIndexToCheck = 0;
278 
279  if (!m_aSpawnpoints.IsEmpty())
280  {
281  UpdateCheckInterval();
282  return;
283  }
284 
285  Enable(false);
286  }
287 
288  //------------------------------------------------------------------------------------------------
289  int GetSpawnpoints(out array<SCR_AmbientVehicleSpawnPointComponent> spawnpoints)
290  {
291  if (spawnpoints)
292  return spawnpoints.Copy(m_aSpawnpoints);
293  else
294  return m_aSpawnpoints.Count();
295  }
296 
297  //------------------------------------------------------------------------------------------------
298  void OnPlayerDisconnected(int playerId, KickCauseCode cause = KickCauseCode.NONE, int timeout = -1)
299  {
300  RefreshPlayerList();
301  }
302 
303  //------------------------------------------------------------------------------------------------
304  void OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
305  {
306  RefreshPlayerList();
307  }
308 }
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
OnAmbientVehicleSpawnedDelegate
func OnAmbientVehicleSpawnedDelegate
Definition: SCR_AmbientVehicleSystem.c:3
AreGameFlagsSet
bool AreGameFlagsSet(EGameFlags checkGameFlags)
Definition: game.c:567
OnAmbientVehicleSpawnedInvoker
ScriptInvokerBase< OnAmbientVehicleSpawnedDelegate > OnAmbientVehicleSpawnedInvoker
Definition: SCR_AmbientVehicleSystem.c:5
EGameFlags
EGameFlags
GameMode Game Flags represented by bit mask.
Definition: game.c:16
func
func
Definition: SCR_AIThreatSystem.c:5
KickCauseCode
KickCauseCode
Definition: KickCauseCode.c:19
Instigator
Definition: Instigator.c:6
m_fTimer
protected float m_fTimer
Definition: SCR_CampaignMilitaryBaseComponent.c:94
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
Enable
void Enable(bool enable)
Definition: SCR_TabViewComponent.c:806
GameSystem
Definition: GameSystem.c:12
distance
float distance
Definition: SCR_DestructibleTreeV2.c:29
IsEnabled
int IsEnabled()
Definition: SCR_BaseManualCameraComponent.c:99
PlayerManager
Definition: PlayerManager.c:12
SCR_AmbientVehicleSystem
Definition: SCR_AmbientVehicleSystem.c:8