Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_PlayersRestrictionZoneManagerComponent.c
Go to the documentation of this file.
1 [ComponentEditorProps(category: "GameScripted/ZoneRestriction", description: "")]
3 {
4 }
5 
6 class 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
15  protected ref map<int, ref SCR_PlayerRestrictionZoneData> m_PlayerRestrictionZoneData = new map<int, ref SCR_PlayerRestrictionZoneData>();
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 
33  m_aRestrictionZones.Insert(zone);
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 
51  ZoneMovedOrDeleted(zone);
52 
53  m_aRestrictionZones.Remove(index);
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 
293  DamageManagerComponent damageManager = DamageManagerComponent.Cast(playerEntity.FindComponent(DamageManagerComponent));
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  {
339  SCR_EditorRestrictionZoneEntity zone = SCR_EditorRestrictionZoneEntity.Cast(editableEntity.GetOwner());
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  //~Todo: Test what happens if player is deleted
383  protected void OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
384  {
385  if (m_aRestrictionZones.IsEmpty())
386  return;
387 
388  if (m_PlayerRestrictionZoneData.Contains(playerId))
389  SetPlayerZoneData(playerId, null, false, false, -1);
390  }
391 
392  //------------------------------------------------------------------------------------------------
393  override void EOnInit(IEntity owner)
394  {
395  GetGame().GetCallqueue().CallLater(DelayedInit, 1);
396  }
397 
398  //------------------------------------------------------------------------------------------------
399  //Delayed init so SCR_PlayersManagerEditorComponent can be found
400  protected void DelayedInit()
401  {
402  m_PlayerManager = GetGame().GetPlayerManager();
403 
404  if (!m_PlayerManager)
405  return;
406 
408  if (!editableEntityCore)
409  return;
410 
411  editableEntityCore.Event_OnEntityTransformChangedServer.Insert(OnEntityTransformChanged);
412 
414  if (gameMode)
415  {
416  gameMode.GetOnPlayerDisconnected().Insert(OnPlayerDisconnect);
417  gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
418  }
419  }
420 
421  //------------------------------------------------------------------------------------------------
422  override void OnPostInit(IEntity owner)
423  {
424  if (!Replication.IsServer())
425  return;
426 
427  SetEventMask(owner, EntityEvent.INIT);
428  }
429 
430  //------------------------------------------------------------------------------------------------
431  override void OnDelete(IEntity owner)
432  {
433  if (!Replication.IsServer())
434  return;
435 
436  if (!m_aRestrictionZones.IsEmpty())
437  GetGame().GetCallqueue().Remove(ZoneCheckUpdate);
438 
440  if (gameMode)
441  {
442  gameMode.GetOnPlayerDisconnected().Remove(OnPlayerDisconnect);
443  gameMode.GetOnPlayerKilled().Remove(OnPlayerKilled);
444  }
445 
447  if (editableEntityCore)
448  editableEntityCore.Event_OnEntityTransformChangedServer.Remove(OnEntityTransformChanged);
449  }
450 }
451 
453 {
454  IEntity m_PlayerEntity;
455  bool m_bInZone;
456  bool m_bInWarningZone;
457  vector m_vZoneCenter;
458 
459  //------------------------------------------------------------------------------------------------
460  // constructor
462  void SCR_PlayerRestrictionZoneData(IEntity playerEntity)
463  {
464  m_PlayerEntity = playerEntity;
465  }
466 }
ComponentEditorProps
SCR_FragmentEntityClass ComponentEditorProps
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
SCR_PlayersRestrictionZoneManagerComponentClass
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:2
SCR_EditableEntityCore
Definition: SCR_EditableEntityCore.c:10
ZoneCheckUpdate
protected void ZoneCheckUpdate(bool updateAll, SCR_EditorRestrictionZoneEntity removedZone=null, array< int > playerIDZoneMoved=null)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:60
OnEntityTransformChanged
protected void OnEntityTransformChanged(SCR_EditableEntityComponent editableEntity, vector prevTransfom[4])
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:332
m_PlayerRestrictionZoneData
protected ref map< int, ref SCR_PlayerRestrictionZoneData > m_PlayerRestrictionZoneData
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:15
KillPlayerOutOfZone
protected void KillPlayerOutOfZone(int playerID, IEntity playerEntity)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:288
ScriptComponent
SCR_SiteSlotEntityClass ScriptComponent
AddRestrictionZone
void AddRestrictionZone(SCR_EditorRestrictionZoneEntity zone)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:28
m_iPlayerCheckIndex
protected int m_iPlayerCheckIndex
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:18
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
OnDelete
override void OnDelete(IEntity owner)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:431
RemoveRestrictionZone
void RemoveRestrictionZone(SCR_EditorRestrictionZoneEntity zone)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:42
ZoneMovedOrDeleted
protected void ZoneMovedOrDeleted(SCR_EditorRestrictionZoneEntity zone, array< int > playerIDZoneMoved=null)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:304
EDamageState
EDamageState
Definition: EDamageState.c:12
Instigator
Definition: Instigator.c:6
m_PlayerManager
SCR_PlayersRestrictionZoneManagerComponentClass m_PlayerManager
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
OnPlayerDisconnect
protected void OnPlayerDisconnect(int playerID)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:375
SCR_PlayerRestrictionZoneData
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:452
ShowWarningUI
protected void ShowWarningUI(int playerID, bool show, ERestrictionZoneWarningType warningIndex, bool centerChanged, vector zoneCenter, float warningRadiusSq, float zoneRadiusSq)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:272
OnPlayerKilled
protected void OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:383
OnPostInit
override void OnPostInit(IEntity owner)
Editable Mine.
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:422
ZONE_CHECK_FREQUENCY
const protected int ZONE_CHECK_FREQUENCY
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:21
ZONE_CHECK_PLAYER_BATCH_AMOUNT
const protected int ZONE_CHECK_PLAYER_BATCH_AMOUNT
The amount of players the manager checks each update. The leftovers will be done next update etc.
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:19
SCR_EditableEntityComponent
Definition: SCR_EditableEntityComponent.c:13
EOnInit
override void EOnInit(IEntity owner)
Initialise this component with data from FactionsManager.
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:393
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
SCR_EditorRestrictionZoneEntity
Definition: SCR_EditorRestrictionZoneEntity.c:5
SetPlayerZoneData
protected void SetPlayerZoneData(int playerID, IEntity playerEntity, bool inZone, bool inWarningZone, ERestrictionZoneWarningType warningType, vector zoneCenter=vector.Zero, float warningRadiusSq=-1, float zoneRadiusSq=-1)
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:248
m_aRestrictionZones
protected ref set< SCR_EditorRestrictionZoneEntity > m_aRestrictionZones
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:12
DamageManagerComponent
Definition: DamageManagerComponent.c:12
ERestrictionZoneWarningType
ERestrictionZoneWarningType
Definition: ERestrictionZoneWarningType.c:4
PlayerManager
Definition: PlayerManager.c:12
DelayedInit
protected void DelayedInit()
Definition: SCR_PlayersRestrictionZoneManagerComponent.c:400
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180