Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_SeizingComponent.c
Go to the documentation of this file.
2 {
3  [Attribute("{59A6F1EBC6C64F79}Prefabs/Logic/SeizingTrigger.et", UIWidgets.ResourceNamePicker, "", "et")]
4  protected ResourceName m_sTriggerPrefab;
5 
6  //------------------------------------------------------------------------------------------------
8  ResourceName GetTriggerPrefab()
9  {
10  return m_sTriggerPrefab;
11  }
12 }
13 
14 void OnTimerChangeFn(WorldTimestamp newStart, WorldTimestamp newEnd);
16 typedef ScriptInvokerBase<OnTimerChangeFn> OnTimerChangeInvoker;
17 
18 class SCR_SeizingComponent : SCR_MilitaryBaseLogicComponent
19 {
20  [Attribute("100")]
21  protected int m_iRadius;
22 
23  [Attribute("7", desc: "Units in a vehicle (most probably aircraft) above this altitude will be ignored.")]
24  protected int m_iMaximumAltitude;
25 
26  [Attribute("10")]
27  protected float m_fMaximumSeizingTime;
28 
29  [Attribute("6")]
30  protected float m_fMinimumSeizingTime;
31 
32  [Attribute("5", "How many characters need to be seizing at once to achieve the minimum seizing time.")]
33  protected int m_iMaximumSeizingCharacters;
34 
35  [Attribute("0", desc: "How long after respawn is player able to start seizing or defending.")]
36  protected float m_fRespawnCooldownPeriod;
37 
38  [Attribute("0", desc: "When checked, the seizing timer will decrease gradually when the seizing is interrupted.")]
39  protected bool m_bGradualTimerReset;
40 
41  [Attribute("0", desc: "Allow seizing for playable factions only.")]
42  protected bool m_bIgnoreNonPlayableAttackers;
43 
44  [Attribute("0", desc: "Allow defending for playable factions only.")]
45  protected bool m_bIgnoreNonPlayableDefenders;
46 
47  [Attribute("1")]
48  protected bool m_bShowNotifications;
49 
50  [Attribute(ENotification.AREA_SEIZING_DONE_FRIENDLIES.ToString(), uiwidget: UIWidgets.ComboBox, enums: ParamEnumArray.FromEnum(ENotification))]
51  protected ENotification m_eCapturedByFriendliesNotification;
52 
53  [Attribute(ENotification.AREA_SEIZING_DONE_ENEMIES.ToString(), uiwidget: UIWidgets.ComboBox, enums: ParamEnumArray.FromEnum(ENotification))]
54  protected ENotification m_eCapturedByEnemiesNotification;
55 
56  [RplProp(onRplName: "OnSeizingTimestampChanged")]
57  protected WorldTimestamp m_fSeizingStartTimestamp;
58 
59  [RplProp(onRplName: "OnSeizingTimestampChanged")]
60  protected WorldTimestamp m_fSeizingEndTimestamp;
61 
62  protected static const float TRIGGER_CHECK_PERIOD_IDLE = 3;
63  protected static const float TRIGGER_CHECK_PERIOD_ACTIVE = 1;
64 
65  protected ref ScriptInvoker m_OnCaptureStart;
66  protected ref ScriptInvoker m_OnCaptureInterrupt;
67  protected ref ScriptInvoker m_OnCaptureFinish;
68  protected ref OnTimerChangeInvoker m_OnTimerChange;
69 
70  protected WorldTimestamp m_fInterruptedCaptureTimestamp;
71  protected float m_fCurrentSeizingTime;
72  protected float m_fInterruptedCaptureDuration;
73  protected SCR_Faction m_PrevailingFaction;
74  protected SCR_Faction m_PrevailingFactionPrevious;
75  protected BaseGameTriggerEntity m_Trigger;
76  protected bool m_bQueryFinished = true;
77  protected bool m_bEnabled = true;
78  protected RplComponent m_RplComponent;
79  protected bool m_bCharacterPresent;
80  protected SCR_FactionAffiliationComponent m_FactionControl;
81  protected int m_iSeizingCharacters;
82  protected ref map<int, WorldTimestamp> m_mSpawnTimers = new map<int, WorldTimestamp>();
83  protected bool m_bDeleteDisabledAIs = false;
84 
85  //------------------------------------------------------------------------------------------------
86  protected bool IsProxy()
87  {
88  return (m_RplComponent && m_RplComponent.IsProxy());
89  }
90 
91  //------------------------------------------------------------------------------------------------
93  int GetRadius()
94  {
95  return m_iRadius;
96  }
97 
98  //------------------------------------------------------------------------------------------------
101  void AllowNotifications(bool allow)
102  {
103  m_bShowNotifications = allow;
104  }
105 
106  //------------------------------------------------------------------------------------------------
109  bool NotificationsAllowed()
110  {
111  return m_bShowNotifications;
112  }
113 
114  //------------------------------------------------------------------------------------------------
116  ScriptInvoker GetOnCaptureStart()
117  {
118  if (!m_OnCaptureStart)
119  m_OnCaptureStart = new ScriptInvoker();
120 
121  return m_OnCaptureStart;
122  }
123 
124  //------------------------------------------------------------------------------------------------
126  ScriptInvoker GetOnCaptureInterrupt()
127  {
128  if (!m_OnCaptureInterrupt)
129  m_OnCaptureInterrupt = new ScriptInvoker();
130 
131  return m_OnCaptureInterrupt;
132  }
133 
134  //------------------------------------------------------------------------------------------------
136  ScriptInvoker GetOnCaptureFinish()
137  {
138  if (!m_OnCaptureFinish)
139  m_OnCaptureFinish = new ScriptInvoker();
140 
141  return m_OnCaptureFinish;
142  }
143 
144  //------------------------------------------------------------------------------------------------
146  OnTimerChangeInvoker GetOnTimerChange()
147  {
148  if (!m_OnTimerChange)
149  m_OnTimerChange = new OnTimerChangeInvoker();
150 
151  return m_OnTimerChange;
152  }
153 
154  //------------------------------------------------------------------------------------------------
155  protected void EvaluatePrevailingFaction()
156  {
157  float delay;
158 
159  // Switch to idle mode when nobody is in the area
160  // Evaluation for all bases should not be done at once, randomize the timer a bit
161  if (m_bCharacterPresent)
162  delay = Math.RandomFloatInclusive(TRIGGER_CHECK_PERIOD_ACTIVE, TRIGGER_CHECK_PERIOD_ACTIVE + (TRIGGER_CHECK_PERIOD_ACTIVE * 0.2));
163  else
164  delay = Math.RandomFloatInclusive(TRIGGER_CHECK_PERIOD_IDLE, TRIGGER_CHECK_PERIOD_IDLE + (TRIGGER_CHECK_PERIOD_IDLE * 0.2));
165 
166  GetGame().GetCallqueue().CallLater(EvaluatePrevailingFaction, delay * 1000);
167 
168  if (!m_bQueryFinished)
169  return;
170 
171  m_Trigger.GetOnQueryFinished().Insert(OnQueryFinished);
172  m_Trigger.QueryEntitiesInside();
173  m_bQueryFinished = false;
174  }
175 
176  //------------------------------------------------------------------------------------------------
177  protected void OnQueryFinished(BaseGameTriggerEntity trigger)
178  {
179  m_bQueryFinished = true;
180 
181  array<IEntity> presentEntities = {};
182  int presentEntitiesCnt = m_Trigger.GetEntitiesInside(presentEntities);
183  m_bCharacterPresent = presentEntitiesCnt != 0;
184 
185  // Nobody is here, no need to evaluate
186  if (!m_bCharacterPresent)
187  {
188  if (m_PrevailingFaction)
189  {
190  m_PrevailingFactionPrevious = m_PrevailingFaction;
191  m_PrevailingFaction = null;
192  OnPrevailingFactionChanged();
193  }
194 
195  return;
196  }
197 
198  map<SCR_Faction, int> factionsPresence = new map<SCR_Faction, int>();
199  SCR_Faction evaluatedEntityFaction;
200 
201  int factionCnt;
202 
203  // Go through all entities and check their factions
204  for (int i = 0; i < presentEntitiesCnt; i++)
205  {
206  IEntity entity = presentEntities[i];
207 
208  if (m_bDeleteDisabledAIs && IsDisabledAI(entity))
209  {
210  RplComponent.DeleteRplEntity(entity, false);
211  continue;
212  }
213 
214  evaluatedEntityFaction = EvaluateEntityFaction(presentEntities[i]);
215 
216  if (!evaluatedEntityFaction)
217  continue;
218 
219  factionCnt = factionsPresence.Get(evaluatedEntityFaction);
220 
221  // If faction is not yet registered, do it now - otherwise just increase its presence counter
222  if (factionCnt == 0)
223  factionsPresence.Insert(evaluatedEntityFaction, 1);
224  else
225  factionsPresence.Set(evaluatedEntityFaction, factionCnt + 1);
226  }
227  m_bDeleteDisabledAIs = false;
228  SCR_Faction prevailingFaction;
229  int highestAttackingPresence;
230  int highestDefendingPresence;
231  int curSeizingCharacters;
232  int presence;
233 
234  // Evaluate the highest attacking presence
235  for (int i = 0, cnt = factionsPresence.Count(); i < cnt; i++)
236  {
237  // Non-playable attackers are not allowed
238  if (m_bIgnoreNonPlayableAttackers && !factionsPresence.GetKey(i).IsPlayable())
239  continue;
240 
241  presence = factionsPresence.GetElement(i);
242 
243  if (presence > highestAttackingPresence)
244  {
245  highestAttackingPresence = presence;
246  prevailingFaction = factionsPresence.GetKey(i);
247  }
248  else if (presence == highestAttackingPresence) // When 2 or more factions have the same presence, none should prevail
249  {
250  prevailingFaction = null;
251  }
252  }
253 
254  // Evaluate the highest defending presence
255  if (prevailingFaction)
256  {
257  for (int i = 0, cnt = factionsPresence.Count(); i < cnt; i++)
258  {
259  // Non-playable defenders are not allowed
260  if (m_bIgnoreNonPlayableDefenders && !factionsPresence.GetKey(i).IsPlayable())
261  continue;
262 
263  // This faction is already considered attacking
264  if (factionsPresence.GetKey(i) == prevailingFaction)
265  continue;
266 
267  highestDefendingPresence = Math.Max(factionsPresence.GetElement(i), highestDefendingPresence);
268  }
269 
270  // Get net amount of players effectively seizing (clamp for max attackers attribute)
271  if (prevailingFaction && highestAttackingPresence > highestDefendingPresence)
272  {
273  curSeizingCharacters = Math.Min(highestAttackingPresence - highestDefendingPresence, m_iMaximumSeizingCharacters);
274  }
275  else
276  {
277  prevailingFaction = null;
278  curSeizingCharacters = 0;
279  }
280  }
281 
282  if (prevailingFaction != m_PrevailingFaction)
283  {
284  m_iSeizingCharacters = curSeizingCharacters;
285  m_PrevailingFactionPrevious = m_PrevailingFaction;
286  m_PrevailingFaction = prevailingFaction;
287  OnPrevailingFactionChanged();
288  }
289  else if (prevailingFaction && curSeizingCharacters != m_iSeizingCharacters)
290  {
291  m_iSeizingCharacters = curSeizingCharacters;
292  RefreshSeizingTimer();
293  }
294  }
295 
296  //------------------------------------------------------------------------------------------------
297  protected SCR_Faction EvaluateEntityFaction(IEntity ent)
298  {
299  SCR_ChimeraCharacter char = SCR_ChimeraCharacter.Cast(ent);
300  if (!char)
301  return null;
302 
303  if (char.IsInVehicle() && SCR_TerrainHelper.GetHeightAboveTerrain(char.GetOrigin()) > m_iMaximumAltitude)
304  return null;
305 
306  CharacterControllerComponent charControl = char.GetCharacterController();
307 
308  if (charControl && charControl.GetLifeState() != ECharacterLifeState.ALIVE)
309  return null;
310 
311  int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(ent);
312  if (!playerId)
313  {
314  AIControlComponent ctrComp = charControl.GetAIControlComponent();
315  if (ctrComp)
316  {
317  AIAgent ai = ctrComp.GetAIAgent();
318  if (ai && ai.GetLOD() == AIAgent.GetMaxLOD())
319  {
320  return null;
321  }
322  }
323  }
324 
325  // Handle after-respawn cooldown
326  if (m_fRespawnCooldownPeriod > 0)
327  {
328 
329  if (playerId != 0 && m_mSpawnTimers.Contains(playerId))
330  {
331  ChimeraWorld world = GetOwner().GetWorld();
332  if (m_mSpawnTimers.Get(playerId).Greater(world.GetServerTimestamp()))
333  return null;
334  else
335  m_mSpawnTimers.Remove(playerId)
336  }
337  }
338 
339  SCR_Faction entityFaction = SCR_Faction.Cast(char.GetFaction());
340 
341  return entityFaction;
342  }
343 
344  //------------------------------------------------------------------------------------------------
345  protected void OnPrevailingFactionChanged()
346  {
347  if (!m_PrevailingFaction || m_FactionControl.GetAffiliatedFaction() == m_PrevailingFaction)
348  {
349  if (m_fSeizingEndTimestamp != 0)
350  {
351  ChimeraWorld world = GetOwner().GetWorld();
352  m_fInterruptedCaptureTimestamp = world.GetServerTimestamp();
353  m_fInterruptedCaptureDuration = m_fInterruptedCaptureTimestamp.DiffMilliseconds(m_fSeizingStartTimestamp);
354  m_fSeizingEndTimestamp = null;
355  m_fSeizingStartTimestamp = null;
356  int factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_PrevailingFactionPrevious);
357  Rpc(RpcDo_OnCaptureInterrupt, factionIndex);
358  RpcDo_OnCaptureInterrupt(factionIndex);
359  }
360  }
361  else
362  {
363  ChimeraWorld world = GetOwner().GetWorld();
364  m_fSeizingStartTimestamp = world.GetServerTimestamp();
365  RefreshSeizingTimer();
366  int factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_PrevailingFaction);
367  Rpc(RpcDo_OnCaptureStart, factionIndex);
368  RpcDo_OnCaptureStart(factionIndex);
369  }
370 
371  OnSeizingTimestampChanged();
372  Replication.BumpMe();
373  }
374 
375  //------------------------------------------------------------------------------------------------
376  protected void OnSeizingTimestampChanged()
377  {
378  if (m_OnTimerChange)
379  m_OnTimerChange.Invoke(m_fSeizingStartTimestamp, m_fSeizingEndTimestamp);
380 
381  if (IsProxy())
382  return;
383 
384  // Run EOnFrame only if timer is actually ticking
385  if (m_fSeizingStartTimestamp == 0 && m_fSeizingEndTimestamp == 0)
386  ClearEventMask(GetOwner(), EntityEvent.FRAME);
387  else
388  SetEventMask(GetOwner(), EntityEvent.FRAME);
389  }
390 
391  //------------------------------------------------------------------------------------------------
393  void RefreshSeizingTimer()
394  {
395  float seizingTimeVar = m_fMaximumSeizingTime - m_fMinimumSeizingTime;
396  float deduct;
397 
398  if (m_iMaximumSeizingCharacters > 1) // Avoid division by 0
399  {
400  float deductPerPlayer = seizingTimeVar / (m_iMaximumSeizingCharacters - 1);
401  deduct = deductPerPlayer * (m_iSeizingCharacters - 1);
402  }
403 
404  m_fSeizingEndTimestamp = m_fSeizingStartTimestamp.PlusSeconds(m_fMaximumSeizingTime - deduct);
405 
406  if (m_bGradualTimerReset && m_fInterruptedCaptureDuration != 0)
407  HandleGradualReset();
408 
409  Replication.BumpMe();
410  OnSeizingTimestampChanged();
411  }
412 
413  //------------------------------------------------------------------------------------------------
415  protected void HandleGradualReset()
416  {
417  float timeSinceInterrupt = m_fSeizingStartTimestamp.DiffMilliseconds(m_fInterruptedCaptureTimestamp);
418 
419  if (timeSinceInterrupt < m_fInterruptedCaptureDuration)
420  {
421  float diff = m_fInterruptedCaptureDuration - timeSinceInterrupt;
422  m_fSeizingStartTimestamp = m_fSeizingStartTimestamp.PlusMilliseconds(-diff);
423  m_fSeizingEndTimestamp = m_fSeizingEndTimestamp.PlusMilliseconds(-diff);
424  }
425 
426  m_fInterruptedCaptureDuration = 0;
427  m_fInterruptedCaptureTimestamp = null;
428  }
429 
430  //------------------------------------------------------------------------------------------------
432  WorldTimestamp GetSeizingStartTimestamp()
433  {
434  return m_fSeizingStartTimestamp;
435  }
436 
437  //------------------------------------------------------------------------------------------------
439  WorldTimestamp GetSeizingEndTimestamp()
440  {
441  return m_fSeizingEndTimestamp;
442  }
443 
444  //------------------------------------------------------------------------------------------------
445  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
446  protected void RpcDo_OnCaptureStart(int factionIndex)
447  {
448  FactionManager factionManager = GetGame().GetFactionManager();
449 
450  if (!factionManager)
451  return;
452 
453  SCR_Faction faction = SCR_Faction.Cast(factionManager.GetFactionByIndex(factionIndex));
454 
455  if (!faction)
456  return;
457 
458  if (m_OnCaptureStart)
459  m_OnCaptureStart.Invoke(faction, this);
460  }
461 
462  //------------------------------------------------------------------------------------------------
463  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
464  protected void RpcDo_OnCaptureInterrupt(int factionIndex)
465  {
466  FactionManager factionManager = GetGame().GetFactionManager();
467 
468  if (!factionManager)
469  return;
470 
471  SCR_Faction faction = SCR_Faction.Cast(factionManager.GetFactionByIndex(factionIndex));
472 
473  if (!faction)
474  return;
475 
476  if (m_OnCaptureInterrupt)
477  m_OnCaptureInterrupt.Invoke(faction, this);
478  }
479 
480  //------------------------------------------------------------------------------------------------
481  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
482  protected void RpcDo_OnCaptureFinish(int factionIndex)
483  {
484  m_bDeleteDisabledAIs = true;
485  FactionManager factionManager = GetGame().GetFactionManager();
486 
487  if (!factionManager)
488  return;
489 
490  SCR_Faction faction = SCR_Faction.Cast(factionManager.GetFactionByIndex(factionIndex));
491 
492  if (!faction)
493  return;
494 
495  if (m_OnCaptureFinish)
496  m_OnCaptureFinish.Invoke(faction, this);
497 
498  UpdateFlagsInHierarchy(faction);
499 
500  if (m_bShowNotifications)
501  NotifyPlayerInRadius(faction);
502 
503  if (!IsProxy())
504  {
505  if (m_FactionControl.GetAffiliatedFaction() != faction)
506  m_FactionControl.SetAffiliatedFaction(faction);
507  }
508  }
509 
510  //------------------------------------------------------------------------------------------------
511  protected void OnPlayerSpawned(int playerId, IEntity controlledEntity)
512  {
513  if (!controlledEntity)
514  return;
515 
516  // Player did not spawn in the area, ignore them
517  if (vector.DistanceSqXZ(controlledEntity.GetOrigin(), GetOwner().GetOrigin()) > (m_iRadius * m_iRadius))
518  return;
519 
520  ChimeraWorld world = GetOwner().GetWorld();
521  m_mSpawnTimers.Set(playerId, world.GetServerTimestamp().PlusSeconds(m_fRespawnCooldownPeriod));
522  }
523 
524  //------------------------------------------------------------------------------------------------
525  protected void UpdateFlagsInHierarchy(notnull SCR_Faction faction)
526  {
527  array<IEntity> queue = {GetOwner()};
528  SCR_FlagComponent flag;
529  IEntity processedEntity;
530  IEntity nextInHierarchy;
531 
532  while (!queue.IsEmpty())
533  {
534  processedEntity = queue[0];
535  queue.Remove(0);
536 
537  flag = SCR_FlagComponent.Cast(processedEntity.FindComponent(SCR_FlagComponent));
538  if (flag)
539  flag.ChangeMaterial(faction.GetFactionFlagMaterial());
540 
541  nextInHierarchy = processedEntity.GetChildren();
542 
543  while (nextInHierarchy)
544  {
545  queue.Insert(nextInHierarchy);
546  nextInHierarchy = nextInHierarchy.GetSibling();
547  }
548  }
549  }
550 
551  //------------------------------------------------------------------------------------------------
552  protected bool GetIsLocalPlayerPresent()
553  {
554  IEntity player = GetGame().GetPlayerManager().GetPlayerControlledEntity(SCR_PlayerController.GetLocalPlayerId());
555  if (!player)
556  return false;
557 
558  return (vector.DistanceSqXZ(player.GetOrigin(), GetOwner().GetOrigin()) <= (m_iRadius * m_iRadius));
559  }
560 
561  //------------------------------------------------------------------------------------------------
562  protected void NotifyPlayerInRadius(notnull SCR_Faction faction)
563  {
564  Faction playerFaction = SCR_FactionManager.SGetLocalPlayerFaction();
565  if (!playerFaction)
566  return;
567 
568  if (!GetIsLocalPlayerPresent())
569  return;
570 
571  if (playerFaction == faction)
572  SCR_NotificationsComponent.SendLocal(m_eCapturedByFriendliesNotification);
573  else
574  SCR_NotificationsComponent.SendLocal(m_eCapturedByEnemiesNotification);
575  }
576 
577  //------------------------------------------------------------------------------------------------
579  Faction GetFaction()
580  {
581  if (m_FactionControl)
582  return m_FactionControl.GetAffiliatedFaction();
583  else
584  return null;
585  }
586 
587  //------------------------------------------------------------------------------------------------
588  override void OnBaseFactionChanged(Faction faction)
589  {
590  super.OnBaseFactionChanged(faction);
591  m_PrevailingFaction = null;
592  }
593  //------------------------------------------------------------------------------------------------
594  bool IsDisabledAI(IEntity ent)
595  {
596 
597  SCR_ChimeraCharacter char = SCR_ChimeraCharacter.Cast(ent);
598  if (!char)
599  return false;
600 
601  CharacterControllerComponent charControl = char.GetCharacterController();
602  if (!charControl)
603  return false;
604 
605  if (charControl.GetLifeState() == ECharacterLifeState.DEAD)
606  return false;
607 
608  int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(ent);
609  if (playerId)
610  return false;
611 
612  AIControlComponent ctrComp = charControl.GetAIControlComponent();
613  if (!ctrComp)
614  return false;
615 
616  if (ctrComp.IsAIActivated())
617  return false;
618  return true;
619 
620  }
621  //------------------------------------------------------------------------------------------------
623  void Disable()
624  {
625  m_bEnabled = false;
626 
627  if (m_Trigger)
628  delete m_Trigger;
629 
630  ClearEventMask(GetOwner(), EntityEvent.FRAME);
631 
632  foreach (SCR_MilitaryBaseComponent base : m_aBases)
633  {
634  if (!base)
635  continue;
636 
637  base.UnregisterLogicComponent(this);
638  }
639 
641 
642  if (gameMode)
643  gameMode.GetOnPlayerSpawned().Remove(OnPlayerSpawned);
644 
645  GetGame().GetCallqueue().Remove(EvaluatePrevailingFaction);
646  }
647 
648  //------------------------------------------------------------------------------------------------
649  override void OnPostInit(IEntity owner)
650  {
651  super.OnPostInit(owner);
652 
653  m_RplComponent = RplComponent.Cast(owner.FindComponent(RplComponent));
654 
655  // All functionality is server-side
656  if (IsProxy())
657  return;
658 
659  if (!m_bEnabled)
660  return;
661 
662  // Attributes check
663  if (m_iRadius <= 0)
664  {
665  Print("SCR_SeizingComponent: Invalid area radius (" + m_iRadius + ")! Terminating...", LogLevel.ERROR);
666  return;
667  }
668 
669  if (m_fMaximumSeizingTime < 0 || m_fMinimumSeizingTime < 0 || m_fMaximumSeizingTime < m_fMinimumSeizingTime)
670  {
671  Print("SCR_SeizingComponent: Invalid seizing time setting (" + m_fMinimumSeizingTime + ", " + m_fMaximumSeizingTime + ")! Terminating...", LogLevel.ERROR);
672  return;
673  }
674 
675  if (m_iMaximumSeizingCharacters <= 0)
676  {
677  Print("SCR_SeizingComponent: Invalid maximum seizing characters (" + m_iMaximumSeizingCharacters + ")! Terminating...", LogLevel.ERROR);
678  return;
679  }
680 
681  if (!GetGame().InPlayMode())
682  return;
683 
684  SCR_SeizingComponentClass componentData = SCR_SeizingComponentClass.Cast(GetComponentData(GetOwner()));
685  if (!componentData)
686  return;
687 
689  if (!m_FactionControl)
690  {
691  Print("SCR_SeizingComponent: Owner is missing SCR_FactionAffiliationComponent! Terminating...", LogLevel.ERROR);
692  return;
693  }
694 
695  Resource triggerResource = Resource.Load(componentData.GetTriggerPrefab());
696  if (!triggerResource)
697  {
698  Print("SCR_SeizingComponent: Trigger resource failed to load! Terminating...", LogLevel.ERROR);
699  return;
700  }
701 
702  // Spawn the trigger locally on server
703  m_Trigger = BaseGameTriggerEntity.Cast(GetGame().SpawnEntityPrefabLocal(triggerResource, GetGame().GetWorld()));
704  if (!m_Trigger)
705  {
706  Print("SCR_SeizingComponent: Trigger failed to spawn! Terminating...", LogLevel.ERROR);
707  return;
708  }
709 
710  m_Trigger.SetSphereRadius(m_iRadius);
711  owner.AddChild(m_Trigger, -1);
712 
713  // Register after-respawn cooldown method
714  if (m_fRespawnCooldownPeriod > 0)
715  {
717 
718  if (gameMode)
719  gameMode.GetOnPlayerSpawned().Insert(OnPlayerSpawned);
720  }
721 
722  GetGame().GetCallqueue().CallLater(EvaluatePrevailingFaction, Math.RandomFloatInclusive(TRIGGER_CHECK_PERIOD_IDLE, TRIGGER_CHECK_PERIOD_IDLE + (TRIGGER_CHECK_PERIOD_IDLE * 0.2)) * 1000);
723  }
724 
725  //------------------------------------------------------------------------------------------------
726  override void EOnFrame(IEntity owner, float timeSlice)
727  {
728  if (m_fSeizingEndTimestamp == 0)
729  return;
730 
731  ChimeraWorld world = owner.GetWorld();
732  if (world.GetServerTimestamp().Less(m_fSeizingEndTimestamp))
733  return;
734 
735  m_fSeizingEndTimestamp = null;
736  m_fSeizingStartTimestamp = null;
737  OnSeizingTimestampChanged();
738 
739  Replication.BumpMe();
740 
741  if (m_FactionControl.GetAffiliatedFaction() != m_PrevailingFaction)
742  {
743  int factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_PrevailingFaction);
744  Rpc(RpcDo_OnCaptureFinish, factionIndex);
745  RpcDo_OnCaptureFinish(factionIndex);
746  }
747  else
748  {
749  int factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_PrevailingFactionPrevious);
750  Rpc(RpcDo_OnCaptureInterrupt, factionIndex);
751  RpcDo_OnCaptureInterrupt(factionIndex);
752  }
753  }
754 
755  //------------------------------------------------------------------------------------------------
756  // destructor
757  void ~SCR_SeizingComponent()
758  {
759  if (m_Trigger)
760  delete m_Trigger;
761 
763  if (gameMode)
764  gameMode.GetOnPlayerSpawned().Remove(OnPlayerSpawned);
765 
766  GetGame().GetCallqueue().Remove(EvaluatePrevailingFaction);
767  }
768 }
SCR_TerrainHelper
Definition: SCR_TerrainHelper.c:1
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
SCR_PlayerController
Definition: SCR_PlayerController.c:31
ECharacterLifeState
ECharacterLifeState
Definition: ECharacterLifeState.c:12
SCR_MilitaryBaseLogicComponentClass
Definition: SCR_MilitaryBaseLogicComponent.c:1
RplProp
SCR_RplTestEntityClass RplProp
Used for handling entity spawning requests for SCR_CatalogEntitySpawnerComponent and inherited classe...
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
OnTimerChangeFn
func OnTimerChangeFn
Definition: SCR_SeizingComponent.c:15
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
func
func
Definition: SCR_AIThreatSystem.c:5
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
ENotification
ENotification
Definition: ENotification.c:4
m_aBases
SCR_MilitaryBaseLogicComponentClass m_aBases
GetOrigin
vector GetOrigin()
Definition: SCR_AIUtilityComponent.c:279
m_sTriggerPrefab
protected ResourceName m_sTriggerPrefab
Definition: SCR_SeizingComponent.c:3
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_SeizingComponentClass
Definition: SCR_SeizingComponent.c:1
SCR_SeizingComponent
Definition: SCR_SeizingComponent.c:18
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
Faction
Definition: Faction.c:12
m_RplComponent
protected RplComponent m_RplComponent
Definition: SCR_CampaignBuildingManagerComponent.c:42
OnTimerChangeInvoker
ScriptInvokerBase< OnTimerChangeFn > OnTimerChangeInvoker
Definition: SCR_SeizingComponent.c:16
m_FactionControl
protected SCR_FactionAffiliationComponent m_FactionControl
Definition: SCR_ServicePointComponent.c:20
m_bEnabled
private bool m_bEnabled
Definition: SCR_BaseManualCameraComponent.c:3
IsInVehicle
proto external bool IsInVehicle()
Returns true if the character is inside a vehicle.
SCR_FactionAffiliationComponent
Definition: SCR_FactionAffiliationComponent.c:10
SCR_FactionManager
void SCR_FactionManager(IEntitySource src, IEntity parent)
Definition: SCR_FactionManager.c:461
SCR_Faction
Definition: SCR_Faction.c:6