Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_PlayersRestrictionZoneManagerComponent.c
Go to the documentation of this file.
1[ComponentEditorProps(category: "GameScripted/ZoneRestriction", description: "")]
5
6class SCR_PlayersRestrictionZoneManagerComponent : ScriptComponent
7{
8 //References
10
11 //Registered restriction zones
12 protected ref set<SCR_EditorRestrictionZoneEntity> m_aRestrictionZones = new set<SCR_EditorRestrictionZoneEntity>();
13
14 //Players data for being in zones
16
17 //Update
18 protected int m_iPlayerCheckIndex = 0;
19 protected const int ZONE_CHECK_PLAYER_BATCH_AMOUNT = 10;
20
21 protected const int ZONE_CHECK_FREQUENCY = 50;
22
23 //============================== ZONE ARRAYS ==============================\\
24
25 //------------------------------------------------------------------------------------------------
29 {
30 if (!zone || !Replication.IsServer() || m_aRestrictionZones.Contains(zone))
31 return;
32
34
35 if (m_aRestrictionZones.Count() == 1)
36 GetGame().GetCallqueue().CallLater(ZoneCheckUpdate, ZONE_CHECK_FREQUENCY, true, false, null, null);
37 }
38
39 //------------------------------------------------------------------------------------------------
43 {
44 if (!zone || !Replication.IsServer())
45 return;
46
47 int index = m_aRestrictionZones.Find(zone);
48 if (index < 0)
49 return;
50
52
54
55 if (m_aRestrictionZones.IsEmpty())
56 GetGame().GetCallqueue().Remove(ZoneCheckUpdate);
57 }
58
59 //------------------------------------------------------------------------------------------------
60 protected void ZoneCheckUpdate(bool updateAll, SCR_EditorRestrictionZoneEntity removedZone = null, array<int> playerIDZoneMoved = null)
61 {
62 array<int> players = {};
63 int playerCount = m_PlayerManager.GetPlayers(players);
64
65 //If no players do not check
66 if (players.IsEmpty())
67 return;
68
69 IEntity playerEntity;
71
72 vector playerEntityPosition;
73 vector restrictionZonePosition;
74 float distanceSqrXZ;
75
76 bool inZone;
77 bool inWarningZone;
78 bool inRemovedZone;
79
80 int startCheckingIndex;
81 int endCheckingIndex;
82
83 bool wasTeleported;
84 bool ignoreWasTeleported;
85
86 //Check if index is greater then player count. If true: Reset
87 if (!updateAll)
88 {
89 if (m_iPlayerCheckIndex >= playerCount)
91
92 //Set the next batch of players to check
94
95 if (endCheckingIndex > playerCount)
96 endCheckingIndex = playerCount;
97
98 startCheckingIndex = m_iPlayerCheckIndex;
99 }
100 else
101 {
102 endCheckingIndex = playerCount;
103 }
104
105 ERestrictionZoneWarningType warningType = 0;
106
107 vector zoneCenter;
108
109 float warningRadiusSq;
110 float zoneRadiusSq;
111 float prevDistanceSqrXZ;
112
113 //Checks a batch of players
114 for (int i = startCheckingIndex; i < endCheckingIndex; i++)
115 {
116 inZone = false;
117 zoneCenter = vector.Zero;
118 inWarningZone = false;
119 prevDistanceSqrXZ = -1;
120
121 playerEntity = m_PlayerManager.GetPlayerControlledEntity(players[i]);
122
123 //Did not find data so add it
124 if (!m_PlayerRestrictionZoneData.Find(players[i], zoneData))
125 {
126 zoneData = new SCR_PlayerRestrictionZoneData(m_PlayerManager.GetPlayerControlledEntity(players[i]));
127 m_PlayerRestrictionZoneData.Insert(players[i], zoneData);
128 }
129
130 //Not the same entity so clear the entity data
131 if (zoneData.m_PlayerEntity != playerEntity && playerEntity != null)
132 SetPlayerZoneData(players[i], playerEntity, false, false, -1);
133
134 //No entity or dead entity clear the data
135 if (playerEntity == null)
136 {
137 //Clear data
138 if (zoneData.m_PlayerEntity != null)
139 SetPlayerZoneData(players[i], null, false, false, -1);
140
141 continue;
142 }
143
144 //Get player entity position
145 playerEntityPosition = playerEntity.GetOrigin();
146
147 //Go over each zone and check if player is in the zone and if it is in the warning zone
149 {
150 if (!zone)
151 continue;
152
153 restrictionZonePosition = zone.GetOrigin();
154 prevDistanceSqrXZ = distanceSqrXZ;
155 distanceSqrXZ = vector.DistanceSqXZ(playerEntityPosition, restrictionZonePosition);
156
157 if (distanceSqrXZ <= zone.GetRestrictionZoneRadiusSq())
158 {
159 //If zone was deleted or moved (and player is still in it)
160 if (zone == removedZone)
161 {
162 inRemovedZone = true;
163 continue;
164 }
165
166 //~ Player is in zone
167 inZone = true;
168
169 //~ Player is in warning zone so show warning UI (Unless the player is safe in any of the other zones)
170 if (distanceSqrXZ > zone.GetWarningZoneRadiusSq() && zone.GetWarningZoneRadius() != zone.GetRestrictionZoneRadius())
171 {
172 inWarningZone = true;
173
174 //~ If no zone set or the center of the zone is closer then the prev set zone then set the zone the player will be guided towards
175 if (zoneCenter == vector.Zero || distanceSqrXZ < prevDistanceSqrXZ)
176 {
177 warningType = zone.GetWarningType();
178 zoneCenter = zone.GetOrigin();
179 warningRadiusSq = zone.GetWarningZoneRadiusSq();
180 zoneRadiusSq = zone.GetRestrictionZoneRadiusSq();
181 }
182 }
183 //In a zone but not in warning part so never show warning as player is safe
184 else if (distanceSqrXZ <= zone.GetWarningZoneRadiusSq())
185 {
186 inWarningZone = false;
187 break;
188 }
189 }
190 //If zone was moved and player in it before but no longer is.
191 else if (zone == removedZone && playerIDZoneMoved && playerIDZoneMoved.Contains(players[i]))
192 {
193 inRemovedZone = true;
194 }
195 //If player out of zone, check if was teleported
196 else if (!ignoreWasTeleported)
197 {
198 //Player was teleported
199 if (distanceSqrXZ >= zone.GetTeleportedZoneRadiusSq())
200 {
201 wasTeleported = true;
202 }
203 //Player walked out so never check if was teleported
204 else
205 {
206 wasTeleported = false;
207 ignoreWasTeleported = true;
208 }
209 }
210 }
211
212 //Player inzone changed
213 if (inZone != m_PlayerRestrictionZoneData[players[i]].m_bInZone)
214 {
215 //If zone was removed by GM and it was the only zone the player was in ignore it
216 if (inRemovedZone && !inZone)
217 {
218 SetPlayerZoneData(players[i], null, false, false, -1);
219 continue;
220 }
221 //Player moved out of zone thus should will be killed
222 else if (!inZone)
223 {
224 //Player was teleported so do not kill
225 if (wasTeleported)
226 {
227 SetPlayerZoneData(players[i], null, false, false, -1);
228 continue;
229 }
230
231 KillPlayerOutOfZone(players[i], playerEntity);
232 SetPlayerZoneData(players[i], null, false, false, -1);
233 continue;
234 }
235 }
236
237 //Update if not killed
238 SetPlayerZoneData(players[i], playerEntity, inZone, inWarningZone, warningType, zoneCenter, warningRadiusSq, zoneRadiusSq);
239 continue;
240 }
241
242 //Set next batch
243 if (!updateAll)
244 m_iPlayerCheckIndex = endCheckingIndex;
245 }
246
247 //------------------------------------------------------------------------------------------------
248 protected void SetPlayerZoneData(int playerID, IEntity playerEntity, bool inZone, bool inWarningZone, ERestrictionZoneWarningType warningType, vector zoneCenter = vector.Zero, float warningRadiusSq = -1, float zoneRadiusSq = -1)
249 {
251
252 if (!m_PlayerRestrictionZoneData.Find(playerID, zoneData))
253 return;
254
255 //~ Left center zone
256 if (!inWarningZone && zoneData.m_bInWarningZone)
257 ShowWarningUI(playerID, false, -1, false, vector.Zero, -1, -1);
258 //~ entered warning zone or zone center point changed
259 else if (inWarningZone && (!zoneData.m_bInWarningZone || zoneCenter != zoneData.m_vZoneCenter))
260 ShowWarningUI(playerID, true, warningType, zoneCenter != zoneData.m_vZoneCenter, zoneCenter, warningRadiusSq, zoneRadiusSq);
261
262 zoneData.m_bInWarningZone = inWarningZone;
263 zoneData.m_PlayerEntity = playerEntity;
264 zoneData.m_bInZone = inZone;
265 zoneData.m_vZoneCenter = zoneCenter;
266
267 m_PlayerRestrictionZoneData[playerID] = zoneData;
268 }
269
270 //------------------------------------------------------------------------------------------------
271 //Show warning HUD
272 protected void ShowWarningUI(int playerID, bool show, ERestrictionZoneWarningType warningIndex, bool centerChanged, vector zoneCenter, float warningRadiusSq, float zoneRadiusSq)
273 {
274 PlayerController playerController = m_PlayerManager.GetPlayerController(playerID);
275
276 if (!playerController)
277 return;
278
279 SCR_PlayerRestrictionZoneWarningComponent warningComponent = SCR_PlayerRestrictionZoneWarningComponent.Cast(playerController.FindComponent(SCR_PlayerRestrictionZoneWarningComponent));
280 if (!warningComponent)
281 return;
282
283 warningComponent.ShowWarningServer(show, warningIndex, centerChanged, zoneCenter, warningRadiusSq, zoneRadiusSq);
284 }
285
286 //------------------------------------------------------------------------------------------------
287 //Kill the player that walked outside of the zone
288 protected void KillPlayerOutOfZone(int playerID, IEntity playerEntity)
289 {
290 if (!playerEntity)
291 return;
292
294
295 if (!damageManager || damageManager.GetState() == EDamageState.DESTROYED)
296 return;
297
298 damageManager.SetHealthScaled(0);
299 SetPlayerZoneData(playerID, null, false, false, -1);
300 }
301
302 //------------------------------------------------------------------------------------------------
303 //A zone was deleted or moved
304 protected void ZoneMovedOrDeleted(SCR_EditorRestrictionZoneEntity zone, array<int> playerIDZoneMoved = null)
305 {
306 if (!zone)
307 return;
308
309 array<int> players = {};
310 m_PlayerManager.GetPlayers(players);
311
312 //If no players do not check
313 if (players.IsEmpty())
314 return;
315
316 //Only one zone so just clear data
317 if (m_aRestrictionZones.Count() == 1)
318 {
319 foreach (int playerID: players)
320 {
321 SetPlayerZoneData(playerID, null, false, false, -1);
322 }
323 }
324 else
325 {
326 ZoneCheckUpdate(true, zone, playerIDZoneMoved);
327 }
328 }
329
330 //------------------------------------------------------------------------------------------------
331 //Check if a zone or player was moved
332 protected void OnEntityTransformChanged(SCR_EditableEntityComponent editableEntity, vector prevTransfom[4])
333 {
334 if (m_aRestrictionZones.IsEmpty() || !editableEntity)
335 return;
336
337 if (editableEntity.GetOwner().Type() == SCR_EditorRestrictionZoneEntity)
338 {
340 if (!zone)
341 return;
342
343 vector playerEntityPosition;
344 vector restrictionZonePosition;
345 float distanceSqrXZ;
346
347 //Get prev zone position
348 restrictionZonePosition = prevTransfom[3];
349
350 array<int> players = {};
351 array<int> playersInZone = {};
352 m_PlayerManager.GetPlayers(players);
353 IEntity playerEntity;
354
355 foreach (int player: players)
356 {
357 playerEntity = m_PlayerManager.GetPlayerControlledEntity(player);
358 if (!playerEntity)
359 continue;
360
361 playerEntityPosition = playerEntity.GetOrigin();
362 distanceSqrXZ = vector.DistanceSqXZ(playerEntityPosition, restrictionZonePosition);
363
364 //Player is in moved zone
365 if (distanceSqrXZ <= zone.GetRestrictionZoneRadiusSq())
366 playersInZone.Insert(player);
367 }
368
369 ZoneMovedOrDeleted(zone, playersInZone);
370 }
371 }
372
373 //------------------------------------------------------------------------------------------------
374 //Player was disconnected
375 protected void OnPlayerDisconnect(int playerID)
376 {
377 if (m_PlayerRestrictionZoneData.Contains(playerID))
378 m_PlayerRestrictionZoneData.Remove(playerID);
379 }
380
381 //------------------------------------------------------------------------------------------------
382 protected void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
383 {
384 if (m_aRestrictionZones.IsEmpty())
385 return;
386
387 if (m_PlayerRestrictionZoneData.Contains(instigatorContextData.GetVictimPlayerID()))
388 SetPlayerZoneData(instigatorContextData.GetVictimPlayerID(), null, false, false, -1);
389 }
390
391 //------------------------------------------------------------------------------------------------
392 override void EOnInit(IEntity owner)
393 {
394 GetGame().GetCallqueue().CallLater(DelayedInit, 1);
395 }
396
397 //------------------------------------------------------------------------------------------------
398 //Delayed init so SCR_PlayersManagerEditorComponent can be found
399 protected void DelayedInit()
400 {
401 m_PlayerManager = GetGame().GetPlayerManager();
402
403 if (!m_PlayerManager)
404 return;
405
407 if (!editableEntityCore)
408 return;
409
410 editableEntityCore.Event_OnEntityTransformChangedServer.Insert(OnEntityTransformChanged);
411
413 if (gameMode)
414 {
416 gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
417 }
418 }
419
420 //------------------------------------------------------------------------------------------------
421 override void OnPostInit(IEntity owner)
422 {
423 if (!Replication.IsServer())
424 return;
425
426 SetEventMask(owner, EntityEvent.INIT);
427 }
428
429 //------------------------------------------------------------------------------------------------
430 override void OnDelete(IEntity owner)
431 {
432 if (!Replication.IsServer())
433 return;
434
435 if (!m_aRestrictionZones.IsEmpty())
436 GetGame().GetCallqueue().Remove(ZoneCheckUpdate);
437
439 if (gameMode)
440 {
442 gameMode.GetOnPlayerKilled().Remove(OnPlayerKilled);
443 }
444
446 if (editableEntityCore)
447 editableEntityCore.Event_OnEntityTransformChangedServer.Remove(OnEntityTransformChanged);
448 }
449}
450
451class SCR_PlayerRestrictionZoneData
452{
453 IEntity m_PlayerEntity;
454 bool m_bInZone;
455 bool m_bInWarningZone;
456 vector m_vZoneCenter;
457
458 //------------------------------------------------------------------------------------------------
459 // constructor
461 void SCR_PlayerRestrictionZoneData(IEntity playerEntity)
462 {
463 m_PlayerEntity = playerEntity;
464 }
465}
ArmaReforgerScripted GetGame()
Definition game.c:1398
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
SCR_BaseGameMode GetGameMode()
override void DelayedInit(IEntity owner)
void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
override void DelayedInit()
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
it takes to automatically cancel a task when no enemy has been killed in the zone
PlayerManager m_PlayerManager
void OnEntityTransformChanged(SCR_EditableEntityComponent editableEntity, vector prevTransfom[4])
ref set< SCR_EditorRestrictionZoneEntity > m_aRestrictionZones
const int ZONE_CHECK_PLAYER_BATCH_AMOUNT
The amount of players the manager checks each update. The leftovers will be done next update etc.
void ZoneMovedOrDeleted(SCR_EditorRestrictionZoneEntity zone, array< int > playerIDZoneMoved=null)
ref map< int, ref SCR_PlayerRestrictionZoneData > m_PlayerRestrictionZoneData
void RemoveRestrictionZone(SCR_EditorRestrictionZoneEntity zone)
void ShowWarningUI(int playerID, bool show, ERestrictionZoneWarningType warningIndex, bool centerChanged, vector zoneCenter, float warningRadiusSq, float zoneRadiusSq)
void SetPlayerZoneData(int playerID, IEntity playerEntity, bool inZone, bool inWarningZone, ERestrictionZoneWarningType warningType, vector zoneCenter=vector.Zero, float warningRadiusSq=-1, float zoneRadiusSq=-1)
void KillPlayerOutOfZone(int playerID, IEntity playerEntity)
void ZoneCheckUpdate(bool updateAll, SCR_EditorRestrictionZoneEntity removedZone=null, array< int > playerIDZoneMoved=null)
void AddRestrictionZone(SCR_EditorRestrictionZoneEntity zone)
void OnPlayerDisconnect(int playerID)
proto external int SetEventMask(notnull IEntity owner, int mask)
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
Main replication API.
Definition Replication.c:14
ScriptInvokerBase< SCR_BaseGameMode_OnPlayerDisconnected > GetOnPlayerDisconnected()
ScriptInvokerBase< SCR_BaseGameMode_OnControllableDestroyed > GetOnPlayerKilled()
void EOnInit(IEntity owner)
Definition Types.c:486
EntityEvent
Various entity events.
Definition EntityEvent.c:14
EDamageState