10 protected static const int CHECK_INTERVAL = 3;
11 protected static const int DESPAWN_TIMEOUT = 10000;
12 protected static const int PARKED_THRESHOLD = 5;
14 protected static const int SPAWN_RADIUS_MIN_SQ = 500 * 500;
15 protected static const int SPAWN_RADIUS_MAX_SQ = 1000 * 1000;
16 protected static const int DESPAWN_RADIUS_DIFF_SQ = 200 * 200;
18 protected ref array<SCR_AmbientVehicleSpawnPointComponent> m_aSpawnpoints = {};
19 protected ref array<IEntity> m_aPlayers = {};
23 protected int m_iLastAssignedIndex;
24 protected int m_iIndexToCheck;
25 protected int m_iSpawnDistanceSq;
26 protected int m_iDespawnDistanceSq;
28 protected float m_fTimer;
29 protected float m_fCheckInterval;
32 override event protected void OnInit()
35 if (m_aSpawnpoints.IsEmpty())
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;
52 gameMode.GetOnPlayerSpawned().Insert(OnPlayerSpawnedOrDeleted);
53 gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
54 gameMode.GetOnPlayerDeleted().Insert(OnPlayerSpawnedOrDeleted);
55 gameMode.GetOnPlayerDisconnected().Insert(OnPlayerDisconnected);
59 override event protected void OnCleanup()
66 gameMode.GetOnPlayerSpawned().Remove(OnPlayerSpawnedOrDeleted);
67 gameMode.GetOnPlayerKilled().Remove(OnPlayerKilled);
68 gameMode.GetOnPlayerDeleted().Remove(OnPlayerSpawnedOrDeleted);
69 gameMode.GetOnPlayerDisconnected().Remove(OnPlayerDisconnected);
73 override event protected void OnUpdate(ESystemPoint point)
81 float timeSlice = GetWorld().GetFixedTimeSlice();
90 ProcessSpawnpoint(m_iIndexToCheck);
93 if (!m_aSpawnpoints.IsIndexValid(m_iIndexToCheck))
98 override event bool ShouldBePaused()
106 World world =
GetGame().GetWorld();
117 if (!m_OnVehicleSpawned)
120 return m_OnVehicleSpawned;
124 protected void UpdateCheckInterval()
126 m_fCheckInterval = CHECK_INTERVAL / m_aSpawnpoints.Count();
130 protected void RefreshPlayerList()
133 array<int> playerIds = {};
135 int playersCount = pc.GetPlayers(playerIds);
137 foreach (
int playerId : playerIds)
139 IEntity player = pc.GetPlayerControlledEntity(playerId);
144 CharacterControllerComponent comp = CharacterControllerComponent.Cast(player.FindComponent(CharacterControllerComponent));
146 if (!comp || comp.IsDead())
149 m_aPlayers.Insert(player);
154 protected void OnPlayerSpawnedOrDeleted(
int playerId, IEntity player)
160 protected void ProcessSpawnpoint(
int spawnpointIndex)
162 SCR_AmbientVehicleSpawnPointComponent spawnpoint = m_aSpawnpoints[spawnpointIndex];
164 if (!spawnpoint || spawnpoint.GetIsDepleted())
167 Vehicle spawnedVeh = spawnpoint.GetSpawnedVehicle();
169 WorldTimestamp currentTime = world.GetServerTimestamp();
170 int respawnPeriod = spawnpoint.GetRespawnPeriod();
174 if (!spawnedVeh && spawnpoint.GetIsSpawnProcessed() && respawnPeriod <= 0)
176 spawnpoint.SetIsDepleted(
true);
182 WorldTimestamp respawnTimestamp = spawnpoint.GetRespawnTimestamp();
185 if (respawnTimestamp.Greater(currentTime))
188 if (spawnpoint.GetIsFirstSpawnDone())
191 if (respawnTimestamp == 0 && respawnPeriod > 0)
193 spawnpoint.SetRespawnTimestamp(currentTime.PlusSeconds(respawnPeriod));
199 vector location = spawnpoint.GetOwner().GetOrigin();
202 if (spawnedVeh && vector.DistanceXZ(spawnedVeh.GetOrigin(), location) > PARKED_THRESHOLD)
205 if (spawnpoint.GetRespawnPeriod() <= 0)
206 spawnpoint.SetIsDepleted(
true);
211 bool playersNear =
false;
212 bool playersFar =
true;
216 foreach (IEntity player : m_aPlayers)
221 distance = vector.DistanceSq(player.GetOrigin(), location);
223 if (
distance < m_iDespawnDistanceSq)
235 if (!spawnedVeh && playersNear)
237 Vehicle vehicle = spawnpoint.SpawnVehicle();
239 if (vehicle && m_OnVehicleSpawned)
240 m_OnVehicleSpawned.Invoke(spawnpoint, vehicle);
246 if (spawnedVeh && playersFar)
248 WorldTimestamp despawnT = spawnpoint.GetDespawnTimer();
251 spawnpoint.SetDespawnTimer(currentTime.PlusMilliseconds(DESPAWN_TIMEOUT));
252 else if (currentTime.Greater(despawnT))
253 spawnpoint.DespawnVehicle();
257 spawnpoint.SetDespawnTimer(
null);
262 void RegisterSpawnpoint(notnull SCR_AmbientVehicleSpawnPointComponent spawnpoint)
267 m_aSpawnpoints.Insert(spawnpoint);
268 spawnpoint.SetID(m_iLastAssignedIndex);
269 m_iLastAssignedIndex++;
270 UpdateCheckInterval();
274 void UnregisterSpawnpoint(notnull SCR_AmbientVehicleSpawnPointComponent spawnpoint)
276 m_aSpawnpoints.RemoveItem(spawnpoint);
279 if (!m_aSpawnpoints.IsEmpty())
281 UpdateCheckInterval();
289 int GetSpawnpoints(out array<SCR_AmbientVehicleSpawnPointComponent> spawnpoints)
292 return spawnpoints.Copy(m_aSpawnpoints);
294 return m_aSpawnpoints.Count();
304 void OnPlayerKilled(
int playerId, IEntity playerEntity, IEntity killerEntity, notnull
Instigator killer)