Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AmbientPatrolSystem.c
Go to the documentation of this file.
1//------------------------------------------------------------------------------------------------
3{
4 override static void InitInfo(WorldSystemInfo outInfo)
5 {
6 outInfo
7 .SetAbstract(false)
8 .SetLocation(ESystemLocation.Server)
9 .AddPoint(ESystemPoint.FixedFrame);
10 }
11
12 protected static const int CHECK_INTERVAL = 3; //s, how often should an individual patrol spawn be checked
13 protected static const int DESPAWN_TIMEOUT = 10000; //ms
14 protected static const int SPAWN_RADIUS_BLOCK_SQ = 150 * 150; // Square value for distance checks
15
16 [Attribute("250", desc: "Minimum allowed spawn distance, in meters.")]
17 protected int m_iMinSpawnDistance;
18
19 [Attribute("1000", desc: "Maximum allowed spawn distance, in meters.")]
20 protected int m_iMaxSpawnDistance;
21
22 [Attribute("200", desc: "Buffer distance, in meters, added beyond spawn distance before entities are despawned.")]
24
25 [Attribute("250", desc: "Minimum allowed despawn distance, in meters.")]
26 protected int m_iMinDespawnDistance;
27
28 [Attribute("1000", desc: "Maximum allowed despawn distance, in meters.")]
29 protected int m_iMaxDespawnDistance;
30
33
37
38 protected ref array<SCR_AmbientPatrolSpawnPointComponent> m_aPatrols = {};
39 protected ref array<IEntity> m_aPlayers = {};
40
41 protected int m_iIndexToCheck;
42 protected int m_iSpawnDistanceSq;
43 protected int m_iDespawnDistanceSq;
44
45 protected float m_fTimer;
46 protected float m_fCheckInterval;
47
48 //------------------------------------------------------------------------------------------------
49 override event protected void OnInit()
50 {
51 // No need to run updates unless some patrols are actually registered
52 if (m_aPatrols.IsEmpty())
53 Enable(false);
54
56
57 // Calculate (de)spawn distance based on view distance, have it squared for faster distance calculation
58 int fractionOfVD = GetGame().GetViewDistance() * 0.3;
59 m_iSpawnDistanceSq = ClampSpawnDistanceSq(fractionOfVD * fractionOfVD);
61
63 if (!gameMode)
64 return;
65
67 gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
70 }
71
72 //------------------------------------------------------------------------------------------------
73 override event protected void OnCleanup()
74 {
76 if (!gameMode)
77 return;
78
80 gameMode.GetOnPlayerKilled().Remove(OnPlayerKilled);
83 }
84
85 //------------------------------------------------------------------------------------------------
86 override event protected void OnUpdatePoint(WorldUpdatePointArgs args)
87 {
88 if (!GetGame().AreGameFlagsSet(EGameFlags.SpawnAI))
89 {
90 Enable(false);
91 return;
92 }
93
94 m_fTimer += args.GetTimeSliceSeconds();
96 return;
97
98 m_fTimer = 0;
99
100 // Don't process spawning at the very start - wait for a save to be applied if it exists
101 // Otherwise full-size groups get spawned even if they are marked as eliminated in the save file
103 return;
104
106 if (!m_aPatrols.IsIndexValid(m_iIndexToCheck))
107 m_iIndexToCheck = 0;
108 }
109
110 //------------------------------------------------------------------------------------------------
111 override event bool ShouldBePaused()
112 {
113 return true;
114 }
115
116 //------------------------------------------------------------------------------------------------
118 {
119 World world = GetGame().GetWorld();
120
121 if (!world)
122 return null;
123
124 return SCR_AmbientPatrolSystem.Cast(world.FindSystem(SCR_AmbientPatrolSystem));
125 }
126
127 //------------------------------------------------------------------------------------------------
128 protected int ClampSpawnDistanceSq(int spawnDistanceSq)
129 {
130 return Math.ClampInt(spawnDistanceSq, m_iMinSpawnDistanceSq, m_iMaxSpawnDistanceSq);
131 }
132
133 //------------------------------------------------------------------------------------------------
134 protected int ClampDespawnDistanceSq(int despawnDistanceSq)
135 {
136 return Math.ClampInt(despawnDistanceSq, m_iMinDespawnDistanceSq, m_iMaxDespawnDistanceSq);
137 }
138
139 //------------------------------------------------------------------------------------------------
140 protected void UpdateCheckInterval()
141 {
143 }
144
145 //------------------------------------------------------------------------------------------------
146 protected void RefreshPlayerList()
147 {
148 m_aPlayers.Clear();
149 array<int> playerIds = {};
150 PlayerManager pc = GetGame().GetPlayerManager();
151 int playersCount = pc.GetPlayers(playerIds);
152
153 foreach (int playerId : playerIds)
154 {
155 IEntity player = pc.GetPlayerControlledEntity(playerId);
156
157 if (!player)
158 continue;
159
160 CharacterControllerComponent comp = CharacterControllerComponent.Cast(player.FindComponent(CharacterControllerComponent));
161
162 if (!comp || comp.IsDead())
163 continue;
164
165 m_aPlayers.Insert(player);
166 }
167 }
168
169 //------------------------------------------------------------------------------------------------
170 protected void OnPlayerSpawnedOrDeleted(int playerId, IEntity player)
171 {
173 }
174
175 //------------------------------------------------------------------------------------------------
176 protected void ProcessSpawnpoint(int spawnpointIndex)
177 {
178 SCR_AmbientPatrolSpawnPointComponent spawnpoint = m_aPatrols[spawnpointIndex];
179 if (!spawnpoint || (spawnpoint.GetMembersAlive() == 0 && !spawnpoint.GetIsSpawned()))
180 return;
181
182 ChimeraWorld world = GetWorld();
183 const WorldTimestamp currentTime = world.GetServerTimestamp();
184 if (spawnpoint.GetRespawnTimestamp().Greater(currentTime))
185 return;
186
187 if (!spawnpoint.GetIsSpawned())
188 {
189 spawnpoint.SpawnPatrol();
190 return;
191 }
192
193 bool playersNear;
194 bool playersVeryNear;
195 bool playersFar = true;
196 vector location = spawnpoint.GetOwner().GetOrigin();
197 int distance;
198
199 int spawnDistanceSq = m_iSpawnDistanceSq;
200 int spawnPointSpawnDistance = spawnpoint.GetSpawnDistanceOverride();
201 if (spawnPointSpawnDistance >= 0)
202 spawnDistanceSq = ClampSpawnDistanceSq(spawnPointSpawnDistance * spawnPointSpawnDistance);
203
204 int despawnDistanceSq = m_iDespawnDistanceSq;
205 int spawnPointDespawnDistance = spawnpoint.GetDespawnDistanceOverride();
206 if (spawnPointDespawnDistance >= 0)
207 despawnDistanceSq = ClampDespawnDistanceSq(spawnPointDespawnDistance * spawnPointDespawnDistance);
208
209 // Define if any player is close enough to spawn or if all players are far enough to despawn
210 foreach (IEntity player : m_aPlayers)
211 {
212 if (!player)
213 continue;
214
215 distance = vector.DistanceSq(player.GetOrigin(), location);
216
217 if (distance > despawnDistanceSq)
218 continue;
219
220 playersFar = false;
221
222 if (distance > spawnDistanceSq)
223 continue;
224
225 playersNear = true;
226
228 continue;
229
230 playersVeryNear = true;
231 break;
232 }
233
234 bool isAIOverLimit;
235 AIWorld aiWorld = GetGame().GetAIWorld();
236 if (aiWorld)
237 {
238 int maxChars = aiWorld.GetLimitOfActiveAIs();
239
240 if (maxChars <= 0)
241 isAIOverLimit = true;
242 else
243 isAIOverLimit = ((float)aiWorld.GetCurrentNumOfActiveAIs() / (float)maxChars) > spawnpoint.GetAILimitThreshold();
244 }
245
246 if (!isAIOverLimit && !playersVeryNear)
247 spawnpoint.SetIsPaused(false);
248
249 if (playersNear && !spawnpoint.GetIsPaused() && !spawnpoint.IsGroupActive())
250 {
251 // Do not spawn the patrol if the AI threshold setting has been reached
252 if (isAIOverLimit)
253 {
254 spawnpoint.SetIsPaused(true); // Make sure a patrol is not spawned too close to players when AI limit suddenly allows spawning of this group
255 return;
256 }
257
258 spawnpoint.ActivateGroup();
259 return;
260 }
261
262 // Delay is used so dying players don't see the despawn happen
263 if (spawnpoint.GetIsSpawned() && playersFar && spawnpoint.IsGroupActive())
264 {
265 const WorldTimestamp despawnT = spawnpoint.GetDespawnTimestamp();
266 if (despawnT == 0)
267 {
268 spawnpoint.SetDespawnTimestamp(currentTime.PlusMilliseconds(DESPAWN_TIMEOUT));
269 }
270 else if (currentTime.Greater(despawnT))
271 {
272 spawnpoint.DeactivateGroup();
273 }
274 }
275 else
276 {
277 spawnpoint.SetDespawnTimestamp(null);
278 }
279 }
280
281 //------------------------------------------------------------------------------------------------
282 void RegisterPatrol(notnull SCR_AmbientPatrolSpawnPointComponent patrol)
283 {
284 if (!IsEnabled())
285 Enable(true);
286
287 m_aPatrols.Insert(patrol);
289 }
290
291 //------------------------------------------------------------------------------------------------
292 void UnregisterPatrol(notnull SCR_AmbientPatrolSpawnPointComponent patrol)
293 {
294 m_aPatrols.RemoveItem(patrol);
295 m_iIndexToCheck = 0;
296
297 if (!m_aPatrols.IsEmpty())
298 {
300 return;
301 }
302
303 Enable(false);
304 }
305
306 //------------------------------------------------------------------------------------------------
307 int GetPatrols(notnull out array<SCR_AmbientPatrolSpawnPointComponent> patrols)
308 {
309 return patrols.Copy(m_aPatrols);
310 }
311
312 //------------------------------------------------------------------------------------------------
313 void OnPlayerDisconnected(int playerId, KickCauseCode cause = KickCauseCode.NONE, int timeout = -1)
314 {
316 }
317
318 //------------------------------------------------------------------------------------------------
319 void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
320 {
322 }
323}
vector location
ArmaReforgerScripted GetGame()
Definition game.c:1398
bool AreGameFlagsSet(EGameFlags checkGameFlags)
Definition game.c:517
EGameFlags
GameMode Game Flags represented by bit mask.
Definition game.c:17
SCR_BaseGameMode GetGameMode()
float distance
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
proto external Managed FindComponent(typename typeName)
Definition Math.c:13
void OnPlayerSpawnedOrDeleted(int playerId, IEntity player)
void RegisterPatrol(notnull SCR_AmbientPatrolSpawnPointComponent patrol)
void ProcessSpawnpoint(int spawnpointIndex)
static SCR_AmbientPatrolSystem GetInstance()
int ClampDespawnDistanceSq(int despawnDistanceSq)
override event bool ShouldBePaused()
ref array< SCR_AmbientPatrolSpawnPointComponent > m_aPatrols
void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
int GetPatrols(notnull out array< SCR_AmbientPatrolSpawnPointComponent > patrols)
void OnPlayerDisconnected(int playerId, KickCauseCode cause=KickCauseCode.NONE, int timeout=-1)
void UnregisterPatrol(notnull SCR_AmbientPatrolSpawnPointComponent patrol)
void OnUpdatePoint(WorldUpdatePointArgs args)
int ClampSpawnDistanceSq(int spawnDistanceSq)
ref array< IEntity > m_aPlayers
ScriptInvokerBase< SCR_BaseGameMode_OnPlayerDisconnected > GetOnPlayerDisconnected()
ScriptInvokerBase< SCR_BaseGameMode_PlayerIdAndEntity > GetOnPlayerSpawned()
ScriptInvokerBase< SCR_BaseGameMode_PlayerIdAndEntity > GetOnPlayerDeleted()
ScriptInvokerBase< SCR_BaseGameMode_OnControllableDestroyed > GetOnPlayerKilled()
static sealed bool IsLoadInProgress(float msSinceLoad=1000.0)
Definition World.c:16
Structure holding world system meta-information required by the engine.
Structure holding extra data of WorldSystem update point.
Definition float.c:13
WorldSystemPoint ESystemPoint
Definition gameLib.c:7
WorldSystemLocation ESystemLocation
Definition gameLib.c:10
SCR_FieldOfViewSettings Attribute
int IsEnabled()
Returns true if the light is enabled.