Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CampaignMilitaryBaseManager.c
Go to the documentation of this file.
7
14
15typedef ScriptInvokerBase<OnSignalChangedDelegate> OnSignalChangedInvoker;
16typedef ScriptInvokerBase<OnAllBasesInitializedDelegate> OnAllBasesInitializedInvoker;
17typedef ScriptInvokerBase<OnLocalPlayerEnteredBaseDelegate> OnLocalPlayerEnteredBaseInvoker;
18typedef ScriptInvokerBase<OnLocalPlayerLeftBaseDelegate> OnLocalPlayerLeftBaseInvoker;
19typedef ScriptInvokerBase<OnLocalFactionCapturedBaseDelegate> OnLocalFactionCapturedBaseInvoker;
20typedef ScriptInvokerBase<OnBaseBuiltDelegate> OnBaseBuiltInvoker;
21
22//------------------------------------------------------------------------------------------------
25{
26 protected static const int PARENT_BASE_DISTANCE_THRESHOLD = 300; //AI patrols closer than this to a base will couterattack
27 protected static const int HQ_NO_REMNANTS_RADIUS = 300; //AI patrols closer than this to main HQs will be removed
28 protected static const int HQ_NO_REMNANTS_PATROL_RADIUS = 600; //AI patrols with a waypoint which is closer than this to main HQs will be removed
29 protected static const int MAX_HQ_SELECTION_ITERATIONS = 20;
30 protected static const int DEPOT_PLAYER_PRESENCE_CHECK_INTERVAL = 2000; //ms
31 protected static const float CP_AVG_DISTANCE_TOLERANCE = 0.25; //highest relative distance tolerance to control points when evaluating main HQs
32 protected static const string ICON_NAME_SUPPLIES = "Slot_Supplies";
33 protected static const float MAX_DIST_TO_BASE = 300;
34 protected static const float PARKED_LIFETIME = 3600;
35
37
39
40 protected ref array<SCR_CampaignMilitaryBaseComponent> m_aBases = {};
41 protected ref array<SCR_CampaignMilitaryBaseComponent> m_aControlPoints = {};
42 protected ref array<SCR_CampaignSuppliesComponent> m_aRemnantSupplyDepots = {};
43
50
51 protected int m_iActiveBases;
52 protected int m_iTargetActiveBases;
54
56
57 protected bool m_bAllBasesInitialized;
58
60 //------------------------------------------------------------------------------------------------
63 {
64 FactionManager factionManager = GetGame().GetFactionManager();
65 array<Faction> factions = {};
66 factionManager.GetFactionsList(factions);
67 SCR_CampaignFaction campaignFaction;
68 array<int> baseCallsignIndexes = {};
69
70 int minBaseCallsignCount = int.MAX;
71 foreach (Faction faction : factions)
72 {
73 campaignFaction = SCR_CampaignFaction.Cast(faction);
74 if (!campaignFaction)
75 continue;
76
77 if (!campaignFaction.IsPlayable())
78 continue;
79
80 if (!campaignFaction.CanBuildBases())
81 continue;
82
83 baseCallsignIndexes = campaignFaction.GetBaseCallsignIndexes();
84
85 // Skip faction that does not use any callsigns
86 if (baseCallsignIndexes.IsEmpty())
87 continue;
88
89 minBaseCallsignCount = Math.Min(minBaseCallsignCount, baseCallsignIndexes.Count());
90 m_mFactionEstablishedBasesAmount.Insert(campaignFaction.GetFactionKey(), 0);
91 }
92
93 int predefinedBaseCallsignCount;
95 {
96 // Skip uninitialized bases
97 if (!base.IsInitialized())
98 continue;
99
100 // Relays do not have callsigns
101 if (base.GetType() == SCR_ECampaignBaseType.RELAY)
102 continue;
103
104 if (base.GetBuiltByPlayers())
105 continue;
106
107 predefinedBaseCallsignCount++;
108 }
109
110 m_iMaxAvailableCallsignsAmount = minBaseCallsignCount - predefinedBaseCallsignCount;
111 }
112
113 //------------------------------------------------------------------------------------------------
116 {
117 FactionKey baseFactionKey;
118 int factionBuiltBases;
119
121 {
122 if (!base.GetBuiltByPlayers())
123 continue;
124
125 baseFactionKey = base.GetBuiltFaction();
126 if (baseFactionKey.IsEmpty())
127 continue;
128
129 factionBuiltBases = m_mFactionEstablishedBasesAmount.Get(baseFactionKey) + 1;
130
131 m_mFactionEstablishedBasesAmount.Set(baseFactionKey, factionBuiltBases);
132 }
133 }
134
135 //------------------------------------------------------------------------------------------------
138 bool CanFactionBuildNewBase(notnull Faction faction)
139 {
140 // Establishing bases is not enabled at all
141 if (!m_Campaign.GetEstablishingBasesEnabled())
142 return false;
143
144 SCR_CampaignFaction campaignFaction = SCR_CampaignFaction.Cast(faction);
145 if (campaignFaction && !campaignFaction.CanBuildBases())
146 return false;
147
148 int factionsWithBuiltBases = m_mFactionEstablishedBasesAmount.Count();
149 if (factionsWithBuiltBases == 0)
150 return true;
151
152 int builtBases = m_mFactionEstablishedBasesAmount.Get(faction.GetFactionKey());
153 int gameModeLimit = m_Campaign.GetFactionEstablishBaseLimit();
154
155 // When Gamemode limit is -1, establishing bases is only limited by callsign availability
156 if (gameModeLimit == -1)
157 return m_iMaxAvailableCallsignsAmount / factionsWithBuiltBases > builtBases;
158 else
159 return Math.Min(gameModeLimit, m_iMaxAvailableCallsignsAmount / factionsWithBuiltBases) > builtBases;
160 }
161
162 //------------------------------------------------------------------------------------------------
170
171 //------------------------------------------------------------------------------------------------
179
180 //------------------------------------------------------------------------------------------------
181 int GetBases(notnull out array<SCR_CampaignMilitaryBaseComponent> bases, Faction faction = null)
182 {
183 bases.Clear();
185 {
186 if (!theBase)
187 continue;
188
189 if (theBase.GetType() != SCR_ECampaignBaseType.BASE && theBase.GetType() != SCR_ECampaignBaseType.SOURCE_BASE)
190 continue;
191
192 if (faction && theBase.GetFaction() != faction)
193 continue;
194
195 bases.Insert(theBase);
196 }
197
198 return bases.Count();
199 }
200
201 //------------------------------------------------------------------------------------------------
204 {
205 return m_iActiveBases;
206 }
207
208 //------------------------------------------------------------------------------------------------
211 {
213 }
214
215 //------------------------------------------------------------------------------------------------
221
222 //------------------------------------------------------------------------------------------------
224 {
225 m_iTargetActiveBases = count;
226 }
227
228 //------------------------------------------------------------------------------------------------
236
237 //------------------------------------------------------------------------------------------------
245
246 //------------------------------------------------------------------------------------------------
255
256 //------------------------------------------------------------------------------------------------
265
266 //------------------------------------------------------------------------------------------------
268 {
270
271 UpdateBases();
272
275
276 if (RplSession.Mode() != RplMode.Dedicated)
277 {
280 }
281
284
285 if (m_Campaign.IsProxy())
286 return;
287
291
293 }
294
295 //------------------------------------------------------------------------------------------------
297 {
299 }
300
301 //------------------------------------------------------------------------------------------------
302 protected void DisableExtraSeizingComponents(SCR_MilitaryBaseComponent base, SCR_MilitaryBaseLogicComponent logic)
303 {
304 if (logic.Type() == SCR_SeizingComponent)
305 SCR_SeizingComponent.Cast(logic).Disable();
306 }
307
308 //------------------------------------------------------------------------------------------------
310 {
311 m_LocalPlayerFaction = faction;
312 }
313
314 //------------------------------------------------------------------------------------------------
319
320 //------------------------------------------------------------------------------------------------
322 int UpdateBases(bool refreshTargetCount = false)
323 {
326 array<SCR_MilitaryBaseComponent> bases = {};
327 baseManager.GetBases(bases);
328
329 m_aBases.Clear();
330 m_aControlPoints.Clear();
331
332 if (refreshTargetCount)
334
335 foreach (SCR_MilitaryBaseComponent base : bases)
336 {
338 if (!campaignBase)
339 continue;
340
341 if (refreshTargetCount && campaignBase.IsInitialized())
343
344 m_aBases.Insert(campaignBase);
345
346 if (campaignBase.IsControlPoint())
347 m_aControlPoints.Insert(campaignBase);
348 }
349
350 return m_aBases.Count();
351 }
352
353 //------------------------------------------------------------------------------------------------
355 void SelectHQs(notnull array<SCR_CampaignMilitaryBaseComponent> candidates, notnull array<SCR_CampaignMilitaryBaseComponent> controlPoints, out notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
356 {
357 int candidatesCount = candidates.Count();
358 if (candidatesCount < 2)
359 return;
360
361 // Pick the same HQs every time when debugging
362 #ifdef ENABLE_DIAG
363 if (SCR_RespawnComponent.Diag_IsCLISpawnEnabled())
364 {
365 SelectHQsSimple(candidates, selectedHQs);
366 return;
367 }
368 #endif
369
370 // If only two HQs are set up, don't waste time with processing
371 if (candidatesCount == 2)
372 {
373 SelectHQsSimple(candidates, selectedHQs);
374 return;
375 }
376
379 array<SCR_CampaignMilitaryBaseComponent> preferredForHQ = {};
380
381 // Pick one of the HQs at random
382 bluforHQ = candidates.GetRandomElement();
383 candidates.RemoveItem(bluforHQ);
384
385 vector bluforHQPos = bluforHQ.GetOwner().GetOrigin();
386 float distanceBetweenHQs;
387 float acceptableDistanceBetweenHQs = m_Campaign.GetAcceptableDistanceBetweenFactionHQs() * m_Campaign.GetAcceptableDistanceBetweenFactionHQs();
388 float preferredDistanceBetweenHQs = m_Campaign.GetPreferredDistanceBetweenFactionHQs() * m_Campaign.GetPreferredDistanceBetweenFactionHQs();
389
390 foreach (SCR_CampaignMilitaryBaseComponent otherHQ : candidates)
391 {
392 // Candidates with a distance to first HQ greater than acceptableDistanceBetweenHQs are acceptable to be picked
393 distanceBetweenHQs = vector.DistanceSqXZ(bluforHQPos, otherHQ.GetOwner().GetOrigin());
394 if (distanceBetweenHQs > acceptableDistanceBetweenHQs)
395 {
396 preferredForHQ.Insert(otherHQ);
397
398 // Candidates with a distance to first HQ greater than preferredDistanceBetweenHQs have double chance to be picked
399 if (distanceBetweenHQs > preferredDistanceBetweenHQs)
400 preferredForHQ.Insert(otherHQ);
401 }
402 }
403
404 // In case none of the candidates are within the acceptable distance, pick any candidate
405 if (preferredForHQ.IsEmpty())
406 opforHQ = candidates.GetRandomElement();
407 else
408 opforHQ = preferredForHQ.GetRandomElement();
409
410 // Randomly assign the factions in reverse in case primary selection gets too limited
411
412 if (Math.RandomFloat01() >= 0.5)
413 selectedHQs = {bluforHQ, opforHQ};
414 else
415 selectedHQs = {opforHQ, bluforHQ};
416 }
417
418 //------------------------------------------------------------------------------------------------
420 protected void SelectHQsSimple(notnull array<SCR_CampaignMilitaryBaseComponent> candidates, out notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
421 {
422 // Pick the same HQs every time when debugging
423#ifdef ENABLE_DIAG
424 if (SCR_RespawnComponent.Diag_IsCLISpawnEnabled())
425 {
426 selectedHQs = {candidates[0], candidates[1]};
427 return;
428 }
429#endif
430
431 // In Tutorial mode, we always want to use the same HQs
432 if (m_Campaign.IsTutorial())
433 {
434 if (candidates[0].GetFaction(true) == m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR))
435 selectedHQs = {candidates[0], candidates[1]};
436 else
437 selectedHQs = {candidates[1], candidates[0]};
438
439 return;
440 }
441
442 SCR_CampaignMilitaryBaseComponent bluforHQ = candidates.GetRandomElement();
443 candidates.RemoveItem(bluforHQ);
444 SCR_CampaignMilitaryBaseComponent opforHQ = candidates.GetRandomElement();
445
446 if (Math.RandomFloat01() >= 0.5)
447 selectedHQs = {bluforHQ, opforHQ};
448 else
449 selectedHQs = {opforHQ, bluforHQ};
450 }
451
452 //------------------------------------------------------------------------------------------------
453 void SetHQFactions(notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
454 {
455 SCR_CampaignFaction factionBLUFOR = m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR);
456 SCR_CampaignFaction factionOPFOR = m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.OPFOR);
457 SCR_CampaignFaction factionINDFOR = m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.INDFOR);
458
459 if (selectedHQs[0].GetFaction() == selectedHQs[1].GetFaction())
460 {
461 // Preset owners are the same or null, assign new owners normally
462 selectedHQs[0].SetFaction(factionBLUFOR);
463 selectedHQs[1].SetFaction(factionOPFOR);
464 }
465 else
466 {
467 // Check if one of the preset owners is invalid, if yes, assign a new owner which is not assigned to the other HQ
468 if (!selectedHQs[0].GetFaction() || selectedHQs[0].GetFaction() == factionINDFOR)
469 {
470 if (selectedHQs[1].GetFaction() == factionBLUFOR)
471 selectedHQs[0].SetFaction(factionOPFOR);
472 else
473 selectedHQs[0].SetFaction(factionBLUFOR);
474 }
475 else if (!selectedHQs[1].GetFaction() || selectedHQs[1].GetFaction() == factionINDFOR)
476 {
477 if (selectedHQs[0].GetFaction() == factionBLUFOR)
478 selectedHQs[1].SetFaction(factionOPFOR);
479 else
480 selectedHQs[1].SetFaction(factionBLUFOR);
481 }
482 }
483 }
484
485 //------------------------------------------------------------------------------------------------
487 protected int GetAvgCPDistanceSq(notnull SCR_CampaignMilitaryBaseComponent HQ, notnull array<SCR_CampaignMilitaryBaseComponent> controlPoints)
488 {
489 int thresholdCP = m_Campaign.GetControlPointTreshold();
490
491 // Avoid division by zero
492 if (thresholdCP == 0)
493 return 0;
494
495 array<SCR_CampaignMilitaryBaseComponent> nearestControlPoints = {};
496
497 int distanceToHQ;
498 int controlPointsCount;
499 int arrayIndex;
500 int nearestControlPointsCount;
501
502 vector HQPos = HQ.GetOwner().GetOrigin();
503
504 foreach (SCR_CampaignMilitaryBaseComponent controlPoint : controlPoints)
505 {
506 if (!controlPoint)
507 continue;
508
509 distanceToHQ = vector.DistanceSqXZ(controlPoint.GetOwner().GetOrigin(), HQPos);
510 controlPointsCount = nearestControlPoints.Count();
511 arrayIndex = controlPointsCount;
512
513 for (int i = 0; i < controlPointsCount; i++)
514 {
515 if (distanceToHQ < vector.DistanceSqXZ(HQPos, nearestControlPoints[i].GetOwner().GetOrigin()))
516 {
517 arrayIndex = i;
518 break;
519 }
520 }
521
522 nearestControlPointsCount = nearestControlPoints.InsertAt(controlPoint, arrayIndex);
523 }
524
525 // Avoid division by zero
526 if (nearestControlPointsCount == 0)
527 return 0;
528
529 if (thresholdCP < nearestControlPointsCount)
530 nearestControlPoints.Resize(thresholdCP);
531
532 int totalDist;
533
534 foreach (SCR_CampaignMilitaryBaseComponent controlPoint : nearestControlPoints)
535 {
536 totalDist += vector.DistanceSqXZ(HQPos, controlPoint.GetOwner().GetOrigin());
537 }
538
539 return totalDist / nearestControlPointsCount;
540 }
541
542 //------------------------------------------------------------------------------------------------
546 protected void GetSharedCallsignPool(notnull array<int> outIndexes)
547 {
548 outIndexes.Clear();
549
550 FactionManager factionManager = GetGame().GetFactionManager();
551 if (!factionManager)
552 return;
553
554 array<Faction> allFactions = {};
555 factionManager.GetFactionsList(allFactions);
556
557 int minCallsignCount = int.MAX;
558 foreach (Faction faction : allFactions)
559 {
560 SCR_CampaignFaction campaignFaction = SCR_CampaignFaction.Cast(faction);
561 if (!campaignFaction || !campaignFaction.IsPlayable())
562 continue;
563
564 if (!campaignFaction.CanBuildBases())
565 continue;
566
567 int count = campaignFaction.GetBaseCallsignIndexes().Count();
568 if (count <= 0)
569 continue;
570
571 if (count < minCallsignCount)
572 minCallsignCount = count;
573 }
574
575 if (minCallsignCount == int.MAX)
576 return;
577
578 for (int i = 0; i < minCallsignCount; i++)
579 outIndexes.Insert(i);
580 }
581
582 //------------------------------------------------------------------------------------------------
583 void InitializeBases(notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs, bool randomizeSupplies)
584 {
585 array<SCR_CampaignMilitaryBaseComponent> basesSorted = {};
586 SCR_CampaignMilitaryBaseComponent baseCheckedAgainst;
587 vector originHQ1 = selectedHQs[0].GetOwner().GetOrigin();
588 vector originHQ2 = selectedHQs[1].GetOwner().GetOrigin();
589 float distanceToHQ;
590 bool indexFound;
591 int callsignIndex;
592 array<int> allCallsignIndexes = {};
593 GetSharedCallsignPool(allCallsignIndexes);
594
595 Faction defaultFaction;
596 BaseRadioComponent radio;
597 BaseTransceiver tsv;
598
599 foreach (int iBase, SCR_CampaignMilitaryBaseComponent campaignBase : m_aBases)
600 {
601 if (!campaignBase.IsInitialized())
602 continue;
603
604 defaultFaction = campaignBase.GetFaction(true);
605
606 // Apply default faction set in FactionAffiliationComponent or INDFOR if undefined
607 if (!campaignBase.GetFaction())
608 {
609 if (defaultFaction)
610 campaignBase.SetFaction(defaultFaction);
611 else
612 campaignBase.SetFaction(m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.INDFOR));
613 }
614
615 // Assign callsign from the shared pool (relays included, so their callsign is searchable AND displayable)
616 callsignIndex = allCallsignIndexes.GetRandomIndex();
617 campaignBase.SetCallsignIndex(allCallsignIndexes[callsignIndex]);
618 allCallsignIndexes.Remove(callsignIndex);
619
620 // Sort bases by distance to a HQ so randomized supplies can be applied fairly (if enabled)
621 if (randomizeSupplies && campaignBase.GetType() == SCR_ECampaignBaseType.BASE)
622 {
623 indexFound = false;
624 distanceToHQ = vector.DistanceSqXZ(originHQ1, campaignBase.GetOwner().GetOrigin());
625
626 for (int i = 0, count = basesSorted.Count(); i < count; i++)
627 {
628 baseCheckedAgainst = basesSorted[i];
629
630 if (distanceToHQ < vector.DistanceSqXZ(originHQ1, baseCheckedAgainst.GetOwner().GetOrigin()))
631 {
632 basesSorted.InsertAt(campaignBase, i);
633 indexFound = true;
634 break;
635 }
636 }
637
638 if (!indexFound)
639 basesSorted.Insert(campaignBase);
640 }
641 }
642
643 if (randomizeSupplies)
644 AddRandomSupplies(basesSorted, selectedHQs);
645 }
646
647 //------------------------------------------------------------------------------------------------
649 void AddRandomSupplies(notnull array<SCR_CampaignMilitaryBaseComponent> basesSorted, notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
650 {
651 array<int> suppliesBufferBLUFOR = {};
652 array<int> suppliesBufferOPFOR = {};
653 int intervalMultiplier = Math.Floor((m_Campaign.GetMaxStartingSupplies() - m_Campaign.GetMinStartingSupplies()) / m_Campaign.GetStartingSuppliesInterval());
654 FactionKey factionToProcess;
655 vector basePosition;
656 float distanceToHQ1;
657 float distanceToHQ2;
658 int suppliesToAdd;
659
660 foreach (SCR_CampaignMilitaryBaseComponent base : basesSorted)
661 {
662 if (base.IsHQ())
663 continue;
664
665 basePosition = base.GetOwner().GetOrigin();
666 distanceToHQ1 = vector.DistanceSq(basePosition, selectedHQs[0].GetOwner().GetOrigin());
667 distanceToHQ2 = vector.DistanceSq(basePosition, selectedHQs[1].GetOwner().GetOrigin());
668
669 if (distanceToHQ1 > distanceToHQ2)
670 factionToProcess = selectedHQs[1].GetCampaignFaction().GetFactionKey();
671 else
672 factionToProcess = selectedHQs[0].GetCampaignFaction().GetFactionKey();
673
674 // Check if we have preset supplies stored in buffer
675 if (factionToProcess == m_Campaign.GetFactionKeyByEnum(SCR_ECampaignFaction.BLUFOR) && !suppliesBufferBLUFOR.IsEmpty())
676 {
677 suppliesToAdd = suppliesBufferBLUFOR[0];
678 suppliesBufferBLUFOR.RemoveOrdered(0);
679 }
680 else if (factionToProcess == m_Campaign.GetFactionKeyByEnum(SCR_ECampaignFaction.OPFOR) && !suppliesBufferOPFOR.IsEmpty())
681 {
682 suppliesToAdd = suppliesBufferOPFOR[0];
683 suppliesBufferOPFOR.RemoveOrdered(0);
684 }
685 else
686 {
687 // Supplies from buffer not applied, add random amount, store to opposite faction's buffer
688 suppliesToAdd = m_Campaign.GetMinStartingSupplies() + (m_Campaign.GetStartingSuppliesInterval() * Math.RandomIntInclusive(0, intervalMultiplier));
689
690 if (factionToProcess == m_Campaign.GetFactionKeyByEnum(SCR_ECampaignFaction.BLUFOR))
691 suppliesBufferOPFOR.Insert(suppliesToAdd);
692 else
693 suppliesBufferBLUFOR.Insert(suppliesToAdd);
694 }
695
696 base.SetStartingSupplies(suppliesToAdd);
697 }
698 }
699
700 //------------------------------------------------------------------------------------------------
703 {
704 IEntity depot;
705 vector origin;
706 MapItem item;
708 MapDescriptorProps props;
709 SCR_MapDescriptorComponent mapDescriptorComponent;
710 int threshold = m_Campaign.GetSupplyDepotIconThreshold();
711 Color colorFIA = m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.INDFOR).GetFactionColor();
712
714 {
715 depot = comp.GetOwner();
716
717 if (!depot)
718 continue;
719
720 mapDescriptorComponent = SCR_MapDescriptorComponent.Cast(depot.FindComponent(SCR_MapDescriptorComponent));
721 if (!mapDescriptorComponent)
722 continue;
723
724 item = mapDescriptorComponent.Item();
725 origin = depot.GetOrigin();
726 closestBase = FindClosestBase(origin);
727 if (!closestBase)
728 continue;
729
730 if (vector.Distance(origin, closestBase.GetOwner().GetOrigin()) <= threshold)
731 {
732 item.SetVisible(true);
733 item.SetImageDef(ICON_NAME_SUPPLIES);
734
735 props = item.GetProps();
736 props.SetIconSize(32, 0.25, 0.25);
737 props.SetFrontColor(colorFIA);
738 props.SetTextVisible(false);
739 props.Activate(true);
740 }
741 else
742 {
743 item.SetVisible(false);
744 }
745 }
746 }
747
748 //------------------------------------------------------------------------------------------------
753
754 //------------------------------------------------------------------------------------------------
756 {
757 SCR_MapDescriptorComponent mapDescriptorComponent;
758 MapItem item;
759
761 {
762 if (base.IsInitialized())
763 continue;
764
765 mapDescriptorComponent = SCR_MapDescriptorComponent.Cast(base.GetOwner().FindComponent(SCR_MapDescriptorComponent));
766
767 if (!mapDescriptorComponent)
768 continue;
769
770 item = mapDescriptorComponent.Item();
771
772 if (!item)
773 continue;
774
775 item.SetVisible(false);
776 }
777 }
778
779 //------------------------------------------------------------------------------------------------
782 {
783 bool newSettingsDetected = SCR_RadioCoverageSystem.UpdateAll();
784 if (newSettingsDetected)
786 }
787
788 //------------------------------------------------------------------------------------------------
792 {
793 if (delay < 0)
794 delay = 0;
795
796 GetGame().GetCallqueue().CallLater(EvaluateControlPoints, delay);
797 }
798
799 //------------------------------------------------------------------------------------------------
800 // Checks whether some faction is winning the game
802 {
803 FactionManager factionManager = GetGame().GetFactionManager();
804 array<Faction> factions = {};
805 factionManager.GetFactionsList(factions);
806
807 int controlPointsHeld;
808 int controlPointsContested;
809 ChimeraWorld world = GetGame().GetWorld();
810 WorldTimestamp currentTime = world.GetServerTimestamp();
811 WorldTimestamp victoryTimestamp;
812 WorldTimestamp blockPauseTimestamp;
813
814 foreach (Faction faction : factions)
815 {
816 SCR_CampaignFaction fCast = SCR_CampaignFaction.Cast(faction);
817
818 if (!fCast || !fCast.IsPlayable())
819 continue;
820
821 controlPointsHeld = 0;
822 controlPointsContested = 0;
823
824 // Update amount of control points currently held by this faction
826 {
827 if (controlPoint.IsInitialized() && controlPoint.GetFaction() == fCast && controlPoint.IsHQRadioTrafficPossible(fCast, SCR_ERadioCoverageStatus.RECEIVE))
828 {
829 controlPointsHeld++;
830
831 if (controlPoint.GetCapturingFaction() && controlPoint.GetCapturingFaction() != fCast)
832 controlPointsContested++
833 }
834 }
835
836 m_Campaign.SetControlPointsHeld(fCast, controlPointsHeld);
837
838 victoryTimestamp = fCast.GetVictoryTimestamp();
839 blockPauseTimestamp = fCast.GetPauseByBlockTimestamp();
840 int controlPointsThreshold = m_Campaign.GetControlPointTreshold();
841
842 // Update timers (if a faction starts winning or a point is contested)
843 if (controlPointsHeld >= controlPointsThreshold)
844 {
845 if ((controlPointsHeld - controlPointsContested) < controlPointsThreshold)
846 {
847 if (blockPauseTimestamp == 0)
848 fCast.SetPauseByBlockTimestamp(currentTime);
849 }
850 else if (blockPauseTimestamp != 0)
851 {
852 fCast.SetVictoryTimestamp(currentTime.PlusMilliseconds(victoryTimestamp.DiffMilliseconds(blockPauseTimestamp)));
853 fCast.SetPauseByBlockTimestamp(null);
854 }
855
856 if (victoryTimestamp == 0)
857 fCast.SetVictoryTimestamp(currentTime.PlusSeconds(m_Campaign.GetVictoryTimer()));
858 }
859 else
860 {
861 fCast.SetVictoryTimestamp(null);
862 fCast.SetPauseByBlockTimestamp(null);
863 }
864 }
865 }
866
867 //------------------------------------------------------------------------------------------------
868 void OnEnemyDetectedByDefenders(SCR_AIGroup group, SCR_AITargetInfo target, AIAgent reporter)
869 {
870 if (!m_aBases || !target || !target.m_Faction || !group)
871 return;
872
873 // Identify the base under attack, notify about it
875 {
876 if (!base || !base.IsInitialized())
877 continue;
878
879 if (base.ContainsGroup(group))
880 {
881 base.NotifyAboutEnemyAttack(target.m_Faction);
882 return;
883 }
884 }
885 }
886
887 //------------------------------------------------------------------------------------------------
889 {
891 float closestBaseDistance = float.MAX;
892
894 {
895 if (!base.IsInitialized())
896 continue;
897
898 if (searchedType > -1 && base.GetType() != searchedType)
899 continue;
900
901 float distance = vector.DistanceSq(base.GetOwner().GetOrigin(), position);
902
903 if (distance < closestBaseDistance)
904 {
905 closestBaseDistance = distance;
906 closestBase = base;
907 }
908 }
909
910 return closestBase;
911 }
912
913 //------------------------------------------------------------------------------------------------
915 {
916 if (callsign == SCR_MilitaryBaseComponent.INVALID_BASE_CALLSIGN)
917 return null;
918
920 {
921 if (!base)
922 continue;
923
924 if (base.GetCallsign() == callsign)
925 return base;
926 }
927
928 return null;
929 }
930
931 //------------------------------------------------------------------------------------------------
933 {
935 {
936 if (!base)
937 continue;
938
939 if (base.GetOwner().GetOrigin() == position)
940 return base;
941 }
942
943 return null;
944 }
945
946 //------------------------------------------------------------------------------------------------
948 {
950 float closestDepotDistance = float.MAX;
951
953 {
954 float distance = vector.DistanceSq(depot.GetOwner().GetOrigin(), position);
955
956 if (distance < closestDepotDistance)
957 {
958 closestDepotDistance = distance;
959 closestDepot = depot;
960 }
961 }
962
963 return closestDepot;
964 }
965
966 //------------------------------------------------------------------------------------------------
967 bool IsEntityInFactionRadioSignal(notnull IEntity entity, notnull Faction faction)
968 {
969 SCR_CampaignFaction factionC = SCR_CampaignFaction.Cast(faction);
970 if (!factionC)
971 return false;
972
973 // Check if the entity is within range of deployed mobile HQ which is able to relay the signal
974 SCR_CampaignMobileAssemblyStandaloneComponent mobileHQ = factionC.GetMobileAssembly();
975
976 if (mobileHQ && mobileHQ.GetOwner() != entity && mobileHQ.IsInRadioRange())
977 {
978 if (vector.DistanceSq(entity.GetOrigin(), mobileHQ.GetOwner().GetOrigin()) < Math.Pow(mobileHQ.GetRadioRange(), 2))
979 return true;
980 }
981
983 {
984 if (!base)
985 continue;
986
987 if (faction != base.GetFaction())
988 continue;
989
990 if (base.GetIsEntityInMyRange(entity) && base.IsHQRadioTrafficPossible(factionC))
991 return true;
992 }
993
994 return false;
995 }
996
997 //------------------------------------------------------------------------------------------------
1002 bool IsPositionInFactionRadioSignal(vector position, notnull Faction faction, float signalRangeOffset = 0)
1003 {
1004 SCR_CampaignFaction campaignFaction = SCR_CampaignFaction.Cast(faction);
1005 if (!campaignFaction)
1006 return false;
1007
1008 // Check if the entity is within range of deployed mobile HQ which is able to relay the signal
1009 SCR_CampaignMobileAssemblyStandaloneComponent mobileHQ = campaignFaction.GetMobileAssembly();
1010 if (mobileHQ && mobileHQ.IsInRadioRange())
1011 {
1012 if (vector.DistanceSq(position, mobileHQ.GetOwner().GetOrigin()) < Math.Pow(mobileHQ.GetRadioRange() + signalRangeOffset, 2))
1013 return true;
1014 }
1015
1017 {
1018 if (!base)
1019 continue;
1020
1021 if (faction != base.GetFaction())
1022 continue;
1023
1024 if (vector.DistanceSq(position, base.GetOwner().GetOrigin()) <= Math.Pow(base.GetRadioRange() + signalRangeOffset, 2) && base.IsHQRadioTrafficPossible(campaignFaction))
1025 return true;
1026 }
1027
1028 return false;
1029 }
1030
1031 //------------------------------------------------------------------------------------------------
1032 //------------------------------------------------------------------------------------------------
1035 {
1037 if (!manager)
1038 return;
1039
1040 array<SCR_AmbientPatrolSpawnPointComponent> patrols = {};
1041 manager.GetPatrols(patrols);
1042
1043 const int distLimit = Math.Pow(PARENT_BASE_DISTANCE_THRESHOLD, 2);
1044 float minDistance;
1046 bool register = true;
1047 float dist;
1048 vector center;
1049
1050 int distLimitHQ = Math.Pow(HQ_NO_REMNANTS_RADIUS, 2);
1051 int distLimitHQPatrol = Math.Pow(HQ_NO_REMNANTS_PATROL_RADIUS, 2);
1052
1053 foreach (SCR_AmbientPatrolSpawnPointComponent patrol : patrols)
1054 {
1055 minDistance = float.MAX;
1056 register = true;
1057 center = patrol.GetOwner().GetOrigin();
1058 nearestBase = null;
1059
1061 {
1062 if (!base.IsInitialized() || base.GetType() == SCR_ECampaignBaseType.RELAY)
1063 continue;
1064
1065 dist = vector.DistanceSqXZ(center, base.GetOwner().GetOrigin());
1066
1067 if (base.IsHQ())
1068 {
1069 if (dist < distLimitHQ)
1070 {
1071 patrol.SetMembersAlive(0);
1072 register = false;
1073 break;
1074 }
1075 else if (dist < distLimitHQPatrol)
1076 {
1077 AIWaypointCycle waypoint = AIWaypointCycle.Cast(patrol.GetWaypoint());
1078
1079 if (waypoint)
1080 {
1081 patrol.SetMembersAlive(0);
1082 register = false;
1083 break;
1084 }
1085 }
1086 }
1087
1088 if (dist > distLimit || dist > minDistance)
1089 continue;
1090
1091 if (!base.IsHQ())
1092 {
1093 nearestBase = base;
1094 minDistance = dist;
1095 }
1096 else
1097 {
1098 register = false;
1099 break;
1100 }
1101 }
1102
1103 if (register && nearestBase)
1104 nearestBase.RegisterRemnants(patrol);
1105 }
1106 }
1107
1108 //------------------------------------------------------------------------------------------------
1109 void OnPlayerDisconnected(int playerId)
1110 {
1111 // If the disconnecting player is currently capturing a base; handle it
1113 {
1114 if (!base.IsInitialized())
1115 continue;
1116
1117 if (base.GetCapturingFaction() && base.GetReconfiguredByID() == playerId)
1118 {
1119 base.EndCapture();
1120 break;
1121 }
1122 }
1123 }
1124
1125 //------------------------------------------------------------------------------------------------
1127 {
1128 if (present)
1129 {
1132 }
1133 else if (m_OnLocalPlayerLeftBase)
1134 {
1136 }
1137 }
1138
1139 //------------------------------------------------------------------------------------------------
1140 protected void OnBaseFactionChanged(SCR_MilitaryBaseComponent base, Faction newFaction)
1141 {
1142 if (!m_Campaign.IsProxy())
1144 }
1145
1146 //------------------------------------------------------------------------------------------------
1147 void OnServiceBuilt(SCR_EServicePointStatus state, notnull SCR_ServicePointComponent serviceComponent)
1148 {
1149
1150 }
1151
1152 //------------------------------------------------------------------------------------------------
1153 void OnServiceRemoved(notnull SCR_MilitaryBaseComponent base, notnull SCR_MilitaryBaseLogicComponent service)
1154 {
1156
1157 if (!campaignBase)
1158 return;
1159
1160 campaignBase.OnServiceRemoved(service);
1161
1162 SCR_CatalogEntitySpawnerComponent spawner = SCR_CatalogEntitySpawnerComponent.Cast(service);
1163
1164 if (!spawner)
1165 return;
1166
1167 spawner.GetOnEntitySpawned().Remove(m_Campaign.OnEntityRequested);
1168 }
1169
1170 //------------------------------------------------------------------------------------------------
1172 void OnDefenderGroupSpawned(notnull SCR_MilitaryBaseLogicComponent service, notnull SCR_AIGroup group)
1173 {
1175
1176 if (!comp)
1177 return;
1178
1179 ScriptInvokerBase<SCR_AIGroupPerceptionOnEnemyDetectedFiltered> onEnemyDetected = comp.m_Perception.GetOnEnemyDetectedFiltered();
1180
1181 if (!onEnemyDetected)
1182 return;
1183
1184 onEnemyDetected.Insert(OnEnemyDetectedByDefenders);
1185
1186 array<SCR_MilitaryBaseComponent> bases = {};
1187 service.GetBases(bases);
1188
1189 foreach (SCR_MilitaryBaseComponent base : bases)
1190 {
1192
1193 if (!campaignBase)
1194 continue;
1195
1196 campaignBase.SetDefendersGroup(group);
1197 }
1198 }
1199
1200 //------------------------------------------------------------------------------------------------
1202 {
1203 }
1204
1205 //------------------------------------------------------------------------------------------------
1207 {
1208 array<SCR_CampaignMilitaryBaseComponent> controlPointsInRange = {};
1209
1210 // Get all Control Points which are now available for capture
1212 {
1213 if (!base.IsInitialized() || base.IsHQ())
1214 continue;
1215
1216 if (base.GetFaction() == faction)
1217 continue;
1218
1219 if (!base.IsHQRadioTrafficPossible(faction))
1220 continue;
1221
1222 controlPointsInRange.Insert(base);
1223 }
1224
1226 int minDistance = int.MAX;
1227
1228 // If there are some Control Points in radio range, find the closest one
1229 if (!controlPointsInRange.IsEmpty())
1230 {
1231 array<SCR_CampaignMilitaryBaseComponent> ownedBases = {};
1232
1233 // Get all bases the given faction currently holds
1235 {
1236 if (!base.IsInitialized())
1237 continue;
1238
1239 if (base.GetFaction() != faction)
1240 continue;
1241
1242 if (!base.IsHQRadioTrafficPossible(faction))
1243 continue;
1244
1245 ownedBases.Insert(base);
1246 }
1247
1248 foreach (SCR_CampaignMilitaryBaseComponent controlPoint : controlPointsInRange)
1249 {
1250 vector positionCP = controlPoint.GetOwner().GetOrigin();
1251
1252 foreach (SCR_CampaignMilitaryBaseComponent base : ownedBases)
1253 {
1254 int distance = vector.DistanceSqXZ(base.GetOwner().GetOrigin(), positionCP);
1255
1256 if (distance > minDistance)
1257 continue;
1258
1259 minDistance = distance;
1260 target = controlPoint;
1261 }
1262 }
1263 }
1264 else // Otherwise, find the Control Point closest to one of the capturable bases
1265 {
1266 array<SCR_CampaignMilitaryBaseComponent> basesInRange = {};
1267
1268 // Get all bases which are now available for capture
1270 {
1271 if (!base.IsInitialized() || base.IsHQ())
1272 continue;
1273
1274 if (base.GetFaction() == faction)
1275 continue;
1276
1277 if (!base.IsHQRadioTrafficPossible(faction))
1278 continue;
1279
1280 basesInRange.Insert(base);
1281 }
1282
1284 {
1285 if (!controlPoint.IsInitialized() || controlPoint.IsHQ())
1286 continue;
1287
1288 if (controlPoint.GetFaction() == faction)
1289 continue;
1290
1291 vector positionCP = controlPoint.GetOwner().GetOrigin();
1292
1293 foreach (SCR_CampaignMilitaryBaseComponent base : basesInRange)
1294 {
1295 int distance = vector.DistanceSqXZ(base.GetOwner().GetOrigin(), positionCP);
1296 bool closer = distance < minDistance;
1297 bool coversControlPoint = base.CanReachByRadio(controlPoint.GetOwner());
1298
1299 if (!coversControlPoint && !closer)
1300 continue;
1301
1302 minDistance = distance;
1303 target = base;
1304 }
1305 }
1306 }
1307
1308 return target;
1309 }
1310
1311 //------------------------------------------------------------------------------------------------
1312 protected void DisablePatrolSpawn(IEntity entity)
1313 {
1314 if (!entity)
1315 return;
1316
1317 array<Managed> outComponents = {};
1318 IEntity child = entity.GetChildren();
1319 while (child)
1320 {
1321 Managed entityComponent = child.FindComponent(SCR_AmbientPatrolSpawnPointComponent);
1322 if (entityComponent)
1323 outComponents.Insert(entityComponent);
1324
1325 child = child.GetSibling();
1326 }
1327
1328 SCR_AmbientPatrolSpawnPointComponent component;
1329 foreach (Managed outComponent : outComponents)
1330 {
1331 component = SCR_AmbientPatrolSpawnPointComponent.Cast(outComponent);
1332 if (!component)
1333 continue;
1334
1335 component.SetMembersAlive(0);
1336 }
1337 }
1338
1339 //------------------------------------------------------------------------------------------------
1340 protected void CreateCampaignMilitaryBase(notnull SCR_MilitaryBaseComponent base)
1341 {
1343 params.TransformMode = ETransformMode.WORLD;
1344 base.GetOwner().GetTransform(params.Transform);
1345
1346 const IEntity entity = GetGame().SpawnEntityPrefab(Resource.Load("{1391CE8C0E255636}Prefabs/Systems/MilitaryBase/ConflictMilitaryBase.et"), null, params);
1348 if (campaignBase)
1349 {
1350 campaignBase.SetFaction(SCR_CampaignFaction.Cast(base.GetFaction(true)));
1351
1352 // Analytics call
1353 campaignBase.OnBaseCreatedAsFOB(base.GetFaction(true));
1354 // The base was not linked yet (e.g. player built), attempt to link it now
1355 const IEntity baseComposition = base.GetOwner().GetParent();
1356 if (baseComposition)
1357 campaignBase.SetBaseBuildingComposition(baseComposition);
1358 }
1359
1360 //SCR_CampaignMilitaryBaseComponent.GetOnFactionChangedExtended().Invoke;
1361
1362 DisablePatrolSpawn(entity);
1363 }
1364
1365 //------------------------------------------------------------------------------------------------
1366 protected void OnBaseRegistered(notnull SCR_MilitaryBaseComponent base)
1367 {
1369 if (campaignBase)
1370 return;
1371
1372 if (GetGame().GetWorld().GetWorldTime() < SCR_GameModeCampaign.BACKEND_DELAY)
1373 return;
1374
1375 GetGame().GetCallqueue().Call(CreateCampaignMilitaryBase, base);
1376 }
1377
1378 //------------------------------------------------------------------------------------------------
1379 protected void OnBaseUnregistered(SCR_MilitaryBaseComponent base)
1380 {
1382 if (!campaignBase)
1383 return;
1384
1385 // HQ candidates are unregistered before active bases is set
1386 if (campaignBase.CanBeHQ() && !campaignBase.IsHQ() && (m_iTargetActiveBases <= 0 || m_Campaign.IsProxy()))
1387 return;
1388
1389 string factionKey = campaignBase.GetBuiltFaction();
1390 if (campaignBase.GetBuiltByPlayers() && !factionKey.IsEmpty())
1391 {
1392 m_mFactionEstablishedBasesAmount.Set(factionKey, m_mFactionEstablishedBasesAmount.Get(factionKey) - 1);
1393
1395 s_OnBaseDisassembled.Invoke(campaignBase, campaignBase.GetFaction(true));
1396 }
1397
1400 }
1401
1402 //------------------------------------------------------------------------------------------------
1404 {
1406 return;
1407
1408 if (!m_Campaign.IsProxy())
1409 {
1410 array<int> callsignsPool = {};
1411 GetSharedCallsignPool(callsignsPool);
1412
1413 // Ignore callsigns which are already assigned to other bases
1414 foreach (SCR_CampaignMilitaryBaseComponent existingBase : m_aBases)
1415 {
1416 if (!existingBase.IsInitialized())
1417 continue;
1418
1419 callsignsPool.RemoveItem(existingBase.GetCallsign());
1420 }
1421
1422 base.SetCallsignIndex(callsignsPool.GetRandomElement());
1423 base.OnCallsignAssigned();
1424
1425 base.SetBuiltByPlayers(true);
1426 base.SetBuiltFaction(base.GetFaction());
1427 base.Initialize();
1428
1429 GetGame().GetCallqueue().CallLater(RecalculateRadioCoverageForced, SCR_GameModeCampaign.MINIMUM_DELAY, false, m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.BLUFOR));
1430 GetGame().GetCallqueue().CallLater(RecalculateRadioCoverageForced, SCR_GameModeCampaign.MINIMUM_DELAY, false, m_Campaign.GetFactionByEnum(SCR_ECampaignFaction.OPFOR));
1431 }
1432
1433 UpdateBases(true);
1434 SetFactionBaseEstablished(base.GetFaction());
1435
1436 if (m_OnBaseBuilt)
1437 m_OnBaseBuilt.Invoke(base, base.GetCampaignFaction());
1438 }
1439
1440 //------------------------------------------------------------------------------------------------
1443 protected void SetFactionBaseEstablished(Faction faction)
1444 {
1445 FactionKey factionKey = faction.GetFactionKey();
1446 m_mFactionEstablishedBasesAmount.Set(factionKey, m_mFactionEstablishedBasesAmount.Get(factionKey) + 1);
1447 }
1448
1449 //------------------------------------------------------------------------------------------------
1452 {
1453 bool newSettingsDetected = SCR_RadioCoverageSystem.UpdateAll(true);
1454
1455 if (newSettingsDetected)
1457 }
1458
1459 //------------------------------------------------------------------------------------------------
1461 {
1462 m_Campaign = campaign;
1464
1465 if (!baseManager)
1466 return;
1467
1468 baseManager.GetOnLogicUnregisteredInBase().Insert(OnServiceRemoved);
1469 baseManager.GetOnBaseFactionChanged().Insert(OnBaseFactionChanged);
1470 baseManager.GetOnBaseUnregistered().Insert(OnBaseUnregistered);
1471
1472 m_Campaign.GetOnStarted().Insert(OnConflictStarted);
1473
1474 if (!Replication.IsServer())
1475 return;
1476
1477 const SCR_MilitaryBaseSystem militaryBaseSystem = SCR_MilitaryBaseSystem.GetInstance();
1478 if (militaryBaseSystem)
1479 {
1480 militaryBaseSystem.GetOnLogicRegisteredInBase().Insert(DisableExtraSeizingComponents);
1481 militaryBaseSystem.GetOnBaseRegistered().Insert(OnBaseRegistered);
1482 }
1483 }
1484
1485 //------------------------------------------------------------------------------------------------
1487 {
1488 //Unregister from script invokers
1490
1491 if (baseManager)
1492 {
1493 baseManager.GetOnLogicUnregisteredInBase().Remove(OnServiceRemoved);
1494 baseManager.GetOnBaseFactionChanged().Remove(OnBaseFactionChanged);
1495 baseManager.GetOnBaseUnregistered().Remove(OnBaseUnregistered);
1496 }
1497
1498 if (m_Campaign)
1499 m_Campaign.GetOnStarted().Remove(OnConflictStarted);
1500
1501 const SCR_MilitaryBaseSystem militaryBaseSystem = SCR_MilitaryBaseSystem.GetInstance();
1502 if (militaryBaseSystem)
1503 {
1504 militaryBaseSystem.GetOnLogicRegisteredInBase().Remove(DisableExtraSeizingComponents);
1505 militaryBaseSystem.GetOnBaseRegistered().Remove(OnBaseRegistered);
1506 }
1507 }
1508}
ArmaReforgerScripted GetGame()
Definition game.c:1398
RplMode
Mode of replication.
Definition RplMode.c:9
vector GetOrigin()
ScriptInvokerBase< OnBaseStateChangedDelegate > OnBaseStateChangedInvoker
ScriptInvokerBase< OnAllBasesInitializedDelegate > OnAllBasesInitializedInvoker
func OnLocalPlayerLeftBaseDelegate
ScriptInvokerBase< OnBaseBuiltDelegate > OnBaseBuiltInvoker
ScriptInvokerBase< OnLocalPlayerEnteredBaseDelegate > OnLocalPlayerEnteredBaseInvoker
func OnSignalChangedDelegate
func OnAllBasesInitializedDelegate
func OnLocalFactionCapturedBaseDelegate
ScriptInvokerBase< OnSignalChangedDelegate > OnSignalChangedInvoker
ScriptInvokerBase< OnLocalFactionCapturedBaseDelegate > OnLocalFactionCapturedBaseInvoker
ScriptInvokerBase< OnLocalPlayerLeftBaseDelegate > OnLocalPlayerLeftBaseInvoker
func OnLocalPlayerEnteredBaseDelegate
SCR_CampaignFaction GetFaction()
void SCR_CampaignSuppliesComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
float distance
vector position
void SCR_GameModeCampaign(IEntitySource src, IEntity parent)
void SCR_RespawnComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition Color.c:13
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external IEntity GetChildren()
proto external IEntity GetSibling()
Definition Math.c:13
Main replication API.
Definition Replication.c:14
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
ScriptInvokerBase< SCR_AIGroupPerceptionOnEnemyDetectedFiltered > GetOnEnemyDetectedFiltered()
ref SCR_AIGroupPerception m_Perception
static SCR_AmbientPatrolSystem GetInstance()
int GetPatrols(notnull out array< SCR_AmbientPatrolSpawnPointComponent > patrols)
SCR_CampaignMobileAssemblyStandaloneComponent GetMobileAssembly()
void SetVictoryTimestamp(WorldTimestamp timestamp)
WorldTimestamp GetPauseByBlockTimestamp()
void SetPauseByBlockTimestamp(WorldTimestamp timestamp)
WorldTimestamp GetVictoryTimestamp()
void RegisterRemnants(notnull SCR_AmbientPatrolSpawnPointComponent remnants)
void OnBaseCreatedAsFOB(Faction establishingFaction)
Event which is triggered when creating a FOB.
void OnServiceRemoved(notnull SCR_MilitaryBaseLogicComponent service)
void CountFactionEstablishedBasesAmount()
Goes through all bases and counts the amount of established bases for each faction.
SCR_CampaignMilitaryBaseComponent FindClosestBase(vector position, SCR_ECampaignBaseType searchedType=-1)
void OnBaseFactionChanged(SCR_MilitaryBaseComponent base, Faction newFaction)
void CreateCampaignMilitaryBase(notnull SCR_MilitaryBaseComponent base)
ref array< SCR_CampaignMilitaryBaseComponent > m_aControlPoints
void SetHQFactions(notnull array< SCR_CampaignMilitaryBaseComponent > selectedHQs)
ref map< FactionKey, int > m_mFactionEstablishedBasesAmount
void RegisterRemnantSupplyDepot(notnull SCR_CampaignSuppliesComponent comp)
void CalculateMaxAvailableCallsignAmount()
Calculates the maximum amount of available callsigns for establishing of new bases.
void RecalculateRadioCoverage(notnull SCR_CampaignFaction faction)
Determine the radio coverage of all bases (no coverage / can be reached / can respond / both ways).
OnLocalPlayerLeftBaseInvoker GetOnLocalPlayerLeftBase()
ref array< SCR_CampaignMilitaryBaseComponent > m_aBases
OnSignalChangedInvoker GetOnSignalChanged()
Triggered when a base's radio coverage changes.
SCR_CampaignMilitaryBaseComponent FindBaseByPosition(vector position)
void SetLocalPlayerFaction(notnull SCR_CampaignFaction faction)
SCR_CampaignMilitaryBaseComponent FindBaseByCallsign(int callsign)
OnAllBasesInitializedInvoker GetOnAllBasesInitialized()
Triggered when all bases have been successfully initialized.
ref OnAllBasesInitializedInvoker m_OnAllBasesInitialized
void OnBaseUnregistered(SCR_MilitaryBaseComponent base)
SCR_CampaignSuppliesComponent FindClosestSupplyDepot(vector position)
void OnBaseInitialized(notnull SCR_CampaignMilitaryBaseComponent base)
void InitializeBases(notnull array< SCR_CampaignMilitaryBaseComponent > selectedHQs, bool randomizeSupplies)
bool CanFactionBuildNewBase(notnull Faction faction)
int UpdateBases(bool refreshTargetCount=false)
Update the list of Conflict bases.
ref OnLocalPlayerLeftBaseInvoker m_OnLocalPlayerLeftBase
SCR_CampaignMilitaryBaseComponent SelectAndReturnPrimaryTarget(notnull SCR_CampaignFaction faction)
void OnBaseRegistered(notnull SCR_MilitaryBaseComponent base)
void OnDefenderGroupSpawned(notnull SCR_MilitaryBaseLogicComponent service, notnull SCR_AIGroup group)
Called when a new AI group is spawned by Free Roam Building.
bool IsPositionInFactionRadioSignal(vector position, notnull Faction faction, float signalRangeOffset=0)
OnLocalPlayerEnteredBaseInvoker GetOnLocalPlayerEnteredBase()
void ProcessRemnantsPresence()
Clean up ambient patrols around Main Operating Bases, assign parent bases where applicable.
void InitializeSupplyDepotIcons()
Show icons only for supply depots close enough to an active base.
int GetActiveBasesCount()
Bases which have been initialized.
void AddRandomSupplies(notnull array< SCR_CampaignMilitaryBaseComponent > basesSorted, notnull array< SCR_CampaignMilitaryBaseComponent > selectedHQs)
Add randomized supplies to each base, calculate batches so each side encounters similarly stacked bas...
static ref OnBaseBuiltInvoker s_OnBaseDisassembled
static ref OnBaseStateChangedInvoker m_OnBaseCreated
void OnEnemyDetectedByDefenders(SCR_AIGroup group, SCR_AITargetInfo target, AIAgent reporter)
void OnServiceBuilt(SCR_EServicePointStatus state, notnull SCR_ServicePointComponent serviceComponent)
ref OnLocalPlayerEnteredBaseInvoker m_OnLocalPlayerEnteredBase
int GetAvgCPDistanceSq(notnull SCR_CampaignMilitaryBaseComponent HQ, notnull array< SCR_CampaignMilitaryBaseComponent > controlPoints)
Returns squared average distance to control points - used for starting HQ location calculations.
void DisableExtraSeizingComponents(SCR_MilitaryBaseComponent base, SCR_MilitaryBaseLogicComponent logic)
void OnLocalPlayerPresenceChanged(notnull SCR_CampaignMilitaryBaseComponent base, bool present)
void SelectHQsSimple(notnull array< SCR_CampaignMilitaryBaseComponent > candidates, out notnull array< SCR_CampaignMilitaryBaseComponent > selectedHQs)
If there are only two candidates for main HQ or the main process fails, HQs are selected simply and c...
bool IsEntityInFactionRadioSignal(notnull IEntity entity, notnull Faction faction)
ref array< SCR_CampaignSuppliesComponent > m_aRemnantSupplyDepots
void SelectHQs(notnull array< SCR_CampaignMilitaryBaseComponent > candidates, notnull array< SCR_CampaignMilitaryBaseComponent > controlPoints, out notnull array< SCR_CampaignMilitaryBaseComponent > selectedHQs)
Picks Main Operating Bases from a list of candidates by checking average distance to active control p...
int GetTargetActiveBasesCount()
Total bases expected to be initialized.
int GetBases(notnull out array< SCR_CampaignMilitaryBaseComponent > bases, Faction faction=null)
void OnServiceRemoved(notnull SCR_MilitaryBaseComponent base, notnull SCR_MilitaryBaseLogicComponent service)
void GetSharedCallsignPool(notnull array< int > outIndexes)
void RecalculateRadioCoverageForced(notnull SCR_CampaignFaction faction)
Determine the radio coverage of all bases (no coverage / can be reached / can respond / both ways).
void SCR_CampaignMilitaryBaseManager(notnull SCR_GameModeCampaign campaign)
OnLogicPresenceChangedInvoker GetOnLogicUnregisteredInBase()
int GetBases(notnull out array< SCR_MilitaryBaseComponent > bases)
OnBaseFactionChangedInvoker GetOnBaseFactionChanged()
OnBaseRegisteredInvoker GetOnBaseRegistered()
static SCR_MilitaryBaseSystem GetInstance()
OnBaseUnregisteredInvoker GetOnBaseUnregistered()
OnLogicPresenceChangedInvoker GetOnLogicRegisteredInBase()
static bool UpdateAll(bool forceRecalculation=false)
Definition Types.c:486
void EntitySpawnParams()
Definition gameLib.c:130
IEntity GetOwner()
Owner entity of the fuel tank.
@ MAX