23 protected static const int PARENT_BASE_DISTANCE_THRESHOLD = 300;
24 protected static const int HQ_NO_REMNANTS_RADIUS = 300;
25 protected static const int HQ_NO_REMNANTS_PATROL_RADIUS = 600;
26 protected static const int MAX_HQ_SELECTION_ITERATIONS = 20;
27 protected static const int DEPOT_PLAYER_PRESENCE_CHECK_INTERVAL = 2000;
28 protected static const float CP_AVG_DISTANCE_TOLERANCE = 0.25;
29 protected static const string ICON_NAME_SUPPLIES =
"Slot_Supplies";
30 protected static const float MAX_DIST_TO_BASE = 300;
31 protected static const float PARKED_LIFETIME = 3600;
37 protected ref array<SCR_CampaignMilitaryBaseComponent> m_aBases = {};
38 protected ref array<SCR_CampaignMilitaryBaseComponent> m_aControlPoints = {};
39 protected ref array<SCR_CampaignSuppliesComponent> m_aRemnantSupplyDepots = {};
46 protected int m_iActiveBases;
47 protected int m_iTargetActiveBases;
49 protected bool m_bAllBasesInitialized;
53 int GetActiveBasesCount()
55 return m_iActiveBases;
60 int GetTargetActiveBasesCount()
62 return m_iTargetActiveBases;
70 if (m_iActiveBases == m_iTargetActiveBases)
71 OnAllBasesInitialized();
75 void AddTargetActiveBase()
77 m_iTargetActiveBases++;
81 void SetTargetActiveBasesCount(
int count)
83 m_iTargetActiveBases = count;
89 if (!m_OnLocalPlayerEnteredBase)
92 return m_OnLocalPlayerEnteredBase;
98 if (!m_OnLocalPlayerLeftBase)
101 return m_OnLocalPlayerLeftBase;
108 if (!m_OnAllBasesInitialized)
111 return m_OnAllBasesInitialized;
118 if (!m_OnSignalChanged)
121 return m_OnSignalChanged;
125 void OnAllBasesInitialized()
127 m_bAllBasesInitialized =
true;
130 if (m_Campaign.IsProxy())
133 if (m_OnAllBasesInitialized)
134 m_OnAllBasesInitialized.Invoke();
136 if (RplSession.Mode() != RplMode.Dedicated)
138 InitializeSupplyDepotIcons();
139 HideUnusedBaseIcons();
142 if (m_Campaign.IsProxy())
146 ProcessRemnantsPresence();
152 bool IsBasesInitDone()
154 return m_bAllBasesInitialized;
158 protected void DisableExtraSeizingComponents(SCR_MilitaryBaseComponent base, SCR_MilitaryBaseLogicComponent logic)
167 m_LocalPlayerFaction = faction;
173 return m_LocalPlayerFaction;
181 array<SCR_MilitaryBaseComponent> bases = {};
182 baseManager.GetBases(bases);
185 m_aControlPoints.Clear();
188 foreach (SCR_MilitaryBaseComponent base : bases)
198 if (campaignBase.IsControlPoint())
199 m_aControlPoints.Insert(campaignBase);
207 void SelectHQs(notnull array<SCR_CampaignMilitaryBaseComponent> candidates, notnull array<SCR_CampaignMilitaryBaseComponent> controlPoints, out notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
210 #ifdef TDM_CLI_SELECTION
211 SelectHQsSimple(candidates, selectedHQs);
215 int candidatesCount = candidates.Count();
218 if (candidatesCount == 2)
220 SelectHQsSimple(candidates, selectedHQs);
225 int totalBasesDistance;
228 array<SCR_CampaignMilitaryBaseComponent> eligibleForHQ;
230 int averageHQDistance;
231 int averageCPDistance;
232 int acceptedCPDistanceDiff;
234 while (!opforHQ && iterations < MAX_HQ_SELECTION_ITERATIONS)
237 totalBasesDistance = 0;
242 bluforHQ = candidates.GetRandomElement();
243 bluforHQPos = bluforHQ.GetOwner().GetOrigin();
248 if (otherHQ == bluforHQ)
251 totalBasesDistance += vector.DistanceSqXZ(bluforHQPos, otherHQ.GetOwner().GetOrigin());
254 averageHQDistance = totalBasesDistance / (candidatesCount - 1);
255 averageCPDistance = GetAvgCPDistanceSq(bluforHQ, controlPoints);
256 acceptedCPDistanceDiff = averageCPDistance * CP_AVG_DISTANCE_TOLERANCE;
260 if (candidate == bluforHQ)
264 if (vector.DistanceSqXZ(bluforHQPos, candidate.GetOwner().GetOrigin()) < averageHQDistance)
268 if (Math.AbsInt(averageCPDistance - GetAvgCPDistanceSq(candidate, controlPoints)) > acceptedCPDistanceDiff)
271 eligibleForHQ.Insert(candidate);
275 if (eligibleForHQ.Count() == 0)
279 opforHQ = eligibleForHQ.GetRandomElement();
285 SelectHQsSimple(candidates, selectedHQs);
290 if (Math.RandomFloat01() >= 0.5)
291 selectedHQs = {bluforHQ, opforHQ};
293 selectedHQs = {opforHQ, bluforHQ};
298 protected void SelectHQsSimple(notnull array<SCR_CampaignMilitaryBaseComponent> candidates, out notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
301 #ifdef TDM_CLI_SELECTION
302 selectedHQs = {candidates[0], candidates[1]};
307 if (m_Campaign.IsTutorial())
310 selectedHQs = {candidates[0], candidates[1]};
312 selectedHQs = {candidates[1], candidates[0]};
319 candidates.RemoveItem(bluforHQ);
322 if (Math.RandomFloat01() >= 0.5)
323 selectedHQs = {bluforHQ, opforHQ};
325 selectedHQs = {opforHQ, bluforHQ};
329 void SetHQFactions(notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
338 selectedHQs[0].SetFaction(factionBLUFOR);
339 selectedHQs[1].SetFaction(factionOPFOR);
346 if (selectedHQs[1].
GetFaction() == factionBLUFOR)
347 selectedHQs[0].SetFaction(factionOPFOR);
349 selectedHQs[0].SetFaction(factionBLUFOR);
353 if (selectedHQs[0].
GetFaction() == factionBLUFOR)
354 selectedHQs[1].SetFaction(factionOPFOR);
356 selectedHQs[1].SetFaction(factionBLUFOR);
365 int thresholdCP = m_Campaign.GetControlPointTreshold();
368 if (thresholdCP == 0)
371 array<SCR_CampaignMilitaryBaseComponent> nearestControlPoints = {};
374 int controlPointsCount;
376 int nearestControlPointsCount;
378 vector HQPos = HQ.GetOwner().GetOrigin();
385 distanceToHQ = vector.DistanceSqXZ(controlPoint.GetOwner().GetOrigin(), HQPos);
386 controlPointsCount = nearestControlPoints.Count();
387 arrayIndex = controlPointsCount;
389 for (
int i = 0; i < controlPointsCount; i++)
391 if (distanceToHQ < vector.DistanceSqXZ(HQPos, nearestControlPoints[i].GetOwner().GetOrigin()))
398 nearestControlPointsCount = nearestControlPoints.InsertAt(controlPoint, arrayIndex);
402 if (nearestControlPointsCount == 0)
405 if (thresholdCP < nearestControlPointsCount)
406 nearestControlPoints.Resize(thresholdCP);
412 totalDist += vector.DistanceSqXZ(HQPos, controlPoint.GetOwner().GetOrigin());
415 return totalDist / nearestControlPointsCount;
419 void InitializeBases(notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs,
bool randomizeSupplies)
421 array<SCR_CampaignMilitaryBaseComponent> basesSorted = {};
423 vector originHQ1 = selectedHQs[0].GetOwner().GetOrigin();
424 vector originHQ2 = selectedHQs[1].GetOwner().GetOrigin();
428 array<int> allCallsignIndexes = {};
429 array<int> callsignIndexesBLUFOR = m_Campaign.GetFactionByEnum(
SCR_ECampaignFaction.BLUFOR).GetBaseCallsignIndexes();
433 foreach (
int indexBLUFOR : callsignIndexesBLUFOR)
435 if (factionOPFOR.GetBaseCallsignByIndex(indexBLUFOR))
436 allCallsignIndexes.Insert(indexBLUFOR);
439 int callsignsCount = allCallsignIndexes.Count();
442 BaseRadioComponent radio;
447 if (!campaignBase.IsInitialized())
450 defaultFaction = campaignBase.GetFaction(
true);
453 if (!campaignBase.GetFaction())
456 campaignBase.SetFaction(defaultFaction);
462 campaignBase.UpdateBasesInRadioRange();
467 callsignIndex = allCallsignIndexes.GetRandomIndex();
468 campaignBase.SetCallsignIndex(allCallsignIndexes[callsignIndex]);
469 allCallsignIndexes.Remove(callsignIndex);
474 campaignBase.SetCallsignIndex(callsignsCount + iBase);
481 distanceToHQ = vector.DistanceSqXZ(originHQ1, campaignBase.GetOwner().GetOrigin());
483 for (
int i = 0, count = basesSorted.Count(); i < count; i++)
485 baseCheckedAgainst = basesSorted[i];
487 if (distanceToHQ < vector.DistanceSqXZ(originHQ1, baseCheckedAgainst.GetOwner().GetOrigin()))
489 basesSorted.InsertAt(campaignBase, i);
496 basesSorted.Insert(campaignBase);
500 if (randomizeSupplies)
501 AddRandomSupplies(basesSorted, selectedHQs);
506 void AddRandomSupplies(notnull array<SCR_CampaignMilitaryBaseComponent> basesSorted, notnull array<SCR_CampaignMilitaryBaseComponent> selectedHQs)
508 array<int> suppliesBufferBLUFOR = {};
509 array<int> suppliesBufferOPFOR = {};
510 int intervalMultiplier = Math.Floor((m_Campaign.GetMaxStartingSupplies() - m_Campaign.GetMinStartingSupplies()) / m_Campaign.GetStartingSuppliesInterval());
511 FactionKey factionToProcess;
522 basePosition = base.GetOwner().GetOrigin();
523 distanceToHQ1 = vector.DistanceSq(basePosition, selectedHQs[0].
GetOwner().
GetOrigin());
524 distanceToHQ2 = vector.DistanceSq(basePosition, selectedHQs[1].
GetOwner().
GetOrigin());
526 if (distanceToHQ1 > distanceToHQ2)
527 factionToProcess = selectedHQs[1].GetCampaignFaction().GetFactionKey();
529 factionToProcess = selectedHQs[0].GetCampaignFaction().GetFactionKey();
532 if (factionToProcess == m_Campaign.GetFactionKeyByEnum(
SCR_ECampaignFaction.BLUFOR) && !suppliesBufferBLUFOR.IsEmpty())
534 suppliesToAdd = suppliesBufferBLUFOR[0];
535 suppliesBufferBLUFOR.RemoveOrdered(0);
537 else if (factionToProcess == m_Campaign.GetFactionKeyByEnum(
SCR_ECampaignFaction.OPFOR) && !suppliesBufferOPFOR.IsEmpty())
539 suppliesToAdd = suppliesBufferOPFOR[0];
540 suppliesBufferOPFOR.RemoveOrdered(0);
545 suppliesToAdd = m_Campaign.GetMinStartingSupplies() + (m_Campaign.GetStartingSuppliesInterval() * Math.RandomIntInclusive(0, intervalMultiplier));
548 suppliesBufferOPFOR.Insert(suppliesToAdd);
550 suppliesBufferBLUFOR.Insert(suppliesToAdd);
553 base.SetStartingSupplies(suppliesToAdd);
560 void UpdateTaskBases(
Faction assignedFaction)
564 if (base.IsInitialized() && base.GetCallsignDisplayName().IsEmpty())
565 base.GetMapDescriptor().HandleMapInfo();
573 array<SCR_BaseTask> tasks = {};
574 taskManager.GetFilteredTasks(tasks, assignedFaction);
583 int baseId = conflictTask.GetTargetBaseId();
590 if (!base || base.GetFaction() == conflictTask.GetTargetFaction())
593 conflictTask.SetTargetBase(base);
599 void InitializeSupplyDepotIcons()
606 SCR_MapDescriptorComponent mapDescriptorComponent;
607 int threshold = m_Campaign.GetSupplyDepotIconThreshold();
612 depot = comp.GetOwner();
617 mapDescriptorComponent = SCR_MapDescriptorComponent.Cast(depot.FindComponent(SCR_MapDescriptorComponent));
619 if (!mapDescriptorComponent)
622 item = mapDescriptorComponent.Item();
623 origin = depot.GetOrigin();
624 closestBase = FindClosestBase(origin);
629 if (vector.Distance(origin, closestBase.GetOwner().GetOrigin()) <= threshold)
631 item.SetVisible(
true);
632 item.SetImageDef(ICON_NAME_SUPPLIES);
634 props = item.GetProps();
635 props.SetIconSize(32, 0.25, 0.25);
636 props.SetFrontColor(colorFIA);
637 props.SetTextVisible(
false);
638 props.Activate(
true);
642 item.SetVisible(
false);
650 m_aRemnantSupplyDepots.Insert(comp);
654 void HideUnusedBaseIcons()
656 SCR_MapDescriptorComponent mapDescriptorComponent;
661 if (base.IsInitialized())
664 mapDescriptorComponent = SCR_MapDescriptorComponent.Cast(base.GetOwner().FindComponent(SCR_MapDescriptorComponent));
666 if (!mapDescriptorComponent)
669 item = mapDescriptorComponent.Item();
674 item.SetVisible(
false);
689 if (!base.IsInitialized())
692 if (base.GetFaction() == faction)
693 base.SetHQRadioConverage(faction, SCR_ECampaignHQRadioComms.NONE);
701 map<SCR_CampaignMilitaryBaseComponent, SCR_ECampaignHQRadioComms> newSettings =
new map<SCR_CampaignMilitaryBaseComponent, SCR_ECampaignHQRadioComms>();
702 array<SCR_CampaignMilitaryBaseComponent> canReceiveHQ = {};
703 array<SCR_CampaignMilitaryBaseComponent> canReachHQ = {};
704 SCR_CampaignMobileAssemblyStandaloneComponent mobileHQComponent = faction.GetMobileAssembly();
705 SCR_ECampaignHQRadioComms connectionMHQ = SCR_ECampaignHQRadioComms.NONE;
710 for (
int i = 0; i < basesCount; i++)
714 if (base.IsInitialized() && (!base.IsHQ() || base.GetFaction() == faction))
715 CheckBaseRadioCoverage(i, base, hq, mobileHQComponent, connectionMHQ, faction, canReceiveHQ, canReachHQ, newSettings);
718 if (i == basesCount - 1 && !processedMHQ && connectionMHQ != SCR_ECampaignHQRadioComms.NONE)
722 if (noMHQNeeded == 0)
723 noMHQNeeded = canReceiveHQ.Count();
725 array<SCR_CampaignMilitaryBaseComponent> connectedBases = {};
726 mobileHQComponent.GetBasesInRange(connectedBases);
727 vector posMHQ = mobileHQComponent.GetOwner().GetOrigin();
731 if (connectedBase.IsHQ() && connectedBase.GetFaction() != faction)
734 CheckBaseMHQConnection(i, connectedBase, connectionMHQ, newSettings, canReceiveHQ, canReachHQ, vector.DistanceXZ(posMHQ, connectedBase.GetOwner().GetOrigin()));
740 if (mobileHQComponent)
741 mobileHQComponent.SetCountOfExclusivelyLinkedBases(canReceiveHQ.Count() - noMHQNeeded);
743 int settingsCount = newSettings.Count();
744 SCR_ECampaignHQRadioComms newCoverage;
747 for (
int i = 0; i < settingsCount; i++)
749 base = newSettings.GetKey(i);
750 newCoverage = newSettings.Get(base);
752 if (base.GetHQRadioCoverage(faction) != newCoverage)
753 base.SetHQRadioConverage(faction, newCoverage);
756 if (settingsCount != 0)
758 EvaluateControlPoints();
759 SelectPrimaryTarget(faction);
764 void CheckBaseRadioCoverage(inout
int i, notnull
SCR_CampaignMilitaryBaseComponent base, notnull
SCR_CampaignMilitaryBaseComponent hq, SCR_CampaignMobileAssemblyStandaloneComponent mobileHQComponent, inout SCR_ECampaignHQRadioComms connectionMHQ, notnull
SCR_CampaignFaction faction, inout notnull array<SCR_CampaignMilitaryBaseComponent> canReceiveHQ, inout notnull array<SCR_CampaignMilitaryBaseComponent> canReachHQ, inout notnull map<SCR_CampaignMilitaryBaseComponent, SCR_ECampaignHQRadioComms> newSettings)
766 bool processedReceive = canReceiveHQ.Contains(base);
767 bool processedReach = canReachHQ.Contains(base);
769 if (processedReceive && processedReach)
774 SCR_ECampaignHQRadioComms newCoverage;
775 SCR_ECampaignHQRadioComms savedCoverage;
784 savedCoverage = newSettings.Get(base);
786 if (processedReceive)
788 canReceive = (savedCoverage == SCR_ECampaignHQRadioComms.RECEIVE);
795 if (receiving.GetFaction() == faction && receiving.CanReachByRadio(base))
805 canReach = (savedCoverage == SCR_ECampaignHQRadioComms.SEND);
812 if (reaching.GetFaction() == faction && base.CanReachByRadio(reaching))
821 if (newSettings.Contains(base))
822 newCoverage = savedCoverage;
824 newCoverage = base.GetHQRadioCoverage(faction);
826 if (!canReceive && !canReach)
828 newCoverage = SCR_ECampaignHQRadioComms.NONE;
832 if (canReceive && !processedReceive)
834 if (canReach || processedReach)
835 newCoverage = SCR_ECampaignHQRadioComms.BOTH_WAYS;
837 newCoverage = SCR_ECampaignHQRadioComms.RECEIVE;
839 canReceiveHQ.Insert(base);
843 if (canReach && !processedReach)
845 if (canReceive || processedReceive)
846 newCoverage = SCR_ECampaignHQRadioComms.BOTH_WAYS;
848 newCoverage = SCR_ECampaignHQRadioComms.SEND;
850 canReachHQ.Insert(base);
855 newSettings.Set(base, newCoverage);
858 if (mobileHQComponent && connectionMHQ != SCR_ECampaignHQRadioComms.BOTH_WAYS)
860 if ((newCoverage == SCR_ECampaignHQRadioComms.BOTH_WAYS || newCoverage == SCR_ECampaignHQRadioComms.RECEIVE) && mobileHQComponent.CanReachByRadio(base))
861 connectionMHQ = newCoverage;
866 void CheckBaseMHQConnection(inout
int i, notnull
SCR_CampaignMilitaryBaseComponent connectedBase, SCR_ECampaignHQRadioComms connectionMHQ, inout notnull map<SCR_CampaignMilitaryBaseComponent, SCR_ECampaignHQRadioComms> newSettings, inout notnull array<SCR_CampaignMilitaryBaseComponent> canReceiveHQ, inout notnull array<SCR_CampaignMilitaryBaseComponent> canReachHQ,
float distance)
868 SCR_ECampaignHQRadioComms coverage = newSettings.Get(connectedBase);
870 if (coverage == SCR_ECampaignHQRadioComms.BOTH_WAYS || coverage == connectionMHQ)
875 if (!canReceiveHQ.Contains(connectedBase))
876 canReceiveHQ.Insert(connectedBase);
880 if (connectionMHQ == SCR_ECampaignHQRadioComms.BOTH_WAYS && connectedBase.GetRadioRange() >
distance)
882 if (!canReachHQ.Contains(connectedBase))
883 canReachHQ.Insert(connectedBase);
888 if (coverage == SCR_ECampaignHQRadioComms.NONE)
891 newSettings.Set(connectedBase, connectionMHQ);
893 newSettings.Set(connectedBase, SCR_ECampaignHQRadioComms.RECEIVE);
895 else if (canReach || coverage == SCR_ECampaignHQRadioComms.SEND)
897 newSettings.Set(connectedBase, SCR_ECampaignHQRadioComms.BOTH_WAYS);
905 array<SCR_CampaignMilitaryBaseComponent> controlPointsInRange = {};
910 if (!base.IsInitialized() || base.IsHQ())
913 if (base.GetFaction() == faction)
916 if (!base.IsHQRadioTrafficPossible(faction))
919 controlPointsInRange.Insert(base);
923 int minDistance =
int.MAX;
926 if (!controlPointsInRange.IsEmpty())
928 array<SCR_CampaignMilitaryBaseComponent> ownedBases = {};
933 if (!base.IsInitialized())
936 if (base.GetFaction() != faction)
939 if (!base.IsHQRadioTrafficPossible(faction))
942 ownedBases.Insert(base);
947 vector positionCP = controlPoint.GetOwner().GetOrigin();
951 int distance = vector.DistanceSqXZ(base.GetOwner().GetOrigin(), positionCP);
957 target = controlPoint;
963 array<SCR_CampaignMilitaryBaseComponent> basesInRange = {};
968 if (!base.IsInitialized() || base.IsHQ())
971 if (base.GetFaction() == faction)
974 if (!base.IsHQRadioTrafficPossible(faction))
977 basesInRange.Insert(base);
980 bool targetCoversControlPoint;
984 if (!controlPoint.IsInitialized() || controlPoint.IsHQ())
987 if (controlPoint.GetFaction() == faction)
990 vector positionCP = controlPoint.GetOwner().GetOrigin();
994 int distance = vector.DistanceSqXZ(base.GetOwner().GetOrigin(), positionCP);
995 bool closer =
distance < minDistance;
996 bool coversControlPoint = base.CanReachByRadio(controlPoint);
999 if (coversControlPoint)
1001 if (targetCoversControlPoint && !closer)
1006 if (targetCoversControlPoint || !closer)
1016 m_Campaign.SetPrimaryTarget(faction, target);
1021 void EvaluateControlPoints()
1023 FactionManager factionManager =
GetGame().GetFactionManager();
1024 array<Faction> factions = {};
1025 factionManager.GetFactionsList(factions);
1027 int controlPointsHeld;
1028 int controlPointsContested;
1030 WorldTimestamp currentTime = world.GetServerTimestamp();
1031 WorldTimestamp victoryTimestamp;
1032 WorldTimestamp blockPauseTimestamp;
1034 foreach (
Faction faction : factions)
1038 if (!fCast || !fCast.IsPlayable())
1041 controlPointsHeld = 0;
1042 controlPointsContested = 0;
1047 if (controlPoint.IsInitialized() && controlPoint.GetFaction() == fCast && controlPoint.IsHQRadioTrafficPossible(fCast, SCR_ECampaignHQRadioComms.RECEIVE))
1049 controlPointsHeld++;
1051 if (controlPoint.GetCapturingFaction() && controlPoint.GetCapturingFaction() != fCast)
1052 controlPointsContested++
1056 m_Campaign.SetControlPointsHeld(fCast, controlPointsHeld);
1058 victoryTimestamp = fCast.GetVictoryTimestamp();
1059 blockPauseTimestamp = fCast.GetPauseByBlockTimestamp();
1060 int controlPointsThreshold = m_Campaign.GetControlPointTreshold();
1063 if (controlPointsHeld >= controlPointsThreshold)
1065 if ((controlPointsHeld - controlPointsContested) < controlPointsThreshold)
1067 if (blockPauseTimestamp == 0)
1068 fCast.SetPauseByBlockTimestamp(currentTime);
1070 else if (blockPauseTimestamp != 0)
1072 fCast.SetVictoryTimestamp(currentTime.PlusMilliseconds(victoryTimestamp.DiffMilliseconds(blockPauseTimestamp)));
1073 fCast.SetPauseByBlockTimestamp(
null);
1076 if (victoryTimestamp == 0)
1077 fCast.SetVictoryTimestamp(currentTime.PlusSeconds(m_Campaign.GetVictoryTimer()));
1081 fCast.SetVictoryTimestamp(
null);
1082 fCast.SetPauseByBlockTimestamp(
null);
1088 void OnEnemyDetectedByDefenders(
SCR_AIGroup group, SCR_AITargetInfo target, AIAgent reporter)
1093 if (!base.IsInitialized())
1096 if (base.ContainsGroup(group))
1098 base.NotifyAboutEnemyAttack(target.m_Faction);
1108 float closestBaseDistance =
float.MAX;
1112 if (!base.IsInitialized())
1117 if (
distance < closestBaseDistance)
1130 if (callsign == SCR_MilitaryBaseComponent.INVALID_BASE_CALLSIGN)
1135 if (base.GetCallsign() == callsign)
1147 if (base.GetOwner().GetOrigin() ==
position)
1155 bool IsEntityInFactionRadioSignal(notnull IEntity entity, notnull
Faction faction)
1163 SCR_CampaignMobileAssemblyStandaloneComponent mobileHQ = factionC.GetMobileAssembly();
1165 if (mobileHQ && mobileHQ.GetOwner() != entity && mobileHQ.IsInRadioRange())
1167 if (vector.DistanceSq(entity.GetOrigin(), mobileHQ.GetOwner().GetOrigin()) < Math.Pow(mobileHQ.GetRadioRange(), 2))
1176 if (faction != base.GetFaction())
1179 if (base.GetIsEntityInMyRange(entity) && base.IsHQRadioTrafficPossible(factionC))
1187 void StoreBasesStates(out notnull array<ref SCR_CampaignBaseStruct> outEntries)
1191 if (!base.IsInitialized())
1195 base.StoreState(
struct);
1196 outEntries.Insert(
struct);
1201 void LoadBasesStates(notnull array<ref SCR_CampaignBaseStruct> entries)
1210 base.LoadState(
struct);
1217 base.UpdateBasesInRadioRange();
1223 void ProcessRemnantsPresence()
1230 array<SCR_AmbientPatrolSpawnPointComponent> patrols = {};
1231 manager.GetPatrols(patrols);
1233 int distLimit = Math.Pow(PARENT_BASE_DISTANCE_THRESHOLD, 2);
1236 bool register =
true;
1240 int distLimitHQ = Math.Pow(HQ_NO_REMNANTS_RADIUS, 2);
1241 int distLimitHQPatrol = Math.Pow(HQ_NO_REMNANTS_PATROL_RADIUS, 2);
1243 foreach (SCR_AmbientPatrolSpawnPointComponent patrol : patrols)
1245 minDistance =
float.MAX;
1247 center = patrol.GetOwner().GetOrigin();
1255 dist = vector.DistanceSqXZ(center, base.GetOwner().GetOrigin());
1258 if (base.IsHQ() && !m_Campaign.WasRemnantsStateLoaded())
1260 if (dist < distLimitHQ)
1262 patrol.SetMembersAlive(0);
1267 else if (dist < distLimitHQPatrol)
1269 AIWaypointCycle waypoint = AIWaypointCycle.Cast(patrol.GetWaypoint());
1273 patrol.SetMembersAlive(0);
1280 if (dist > distLimit || dist > minDistance)
1295 if (
register && nearestBase)
1296 nearestBase.RegisterRemnants(patrol);
1306 if (!base.IsInitialized())
1309 if (base.GetCapturingFaction() && base.GetReconfiguredByID() == playerId)
1322 if (m_OnLocalPlayerEnteredBase)
1323 m_OnLocalPlayerEnteredBase.Invoke(base);
1325 else if (m_OnLocalPlayerLeftBase)
1327 m_OnLocalPlayerLeftBase.Invoke(base);
1334 if (!m_Campaign.IsProxy())
1335 EvaluateControlPoints();
1339 void OnServiceBuilt(SCR_EServicePointStatus state, notnull SCR_ServicePointComponent serviceComponent)
1345 void OnServiceRemoved(notnull SCR_MilitaryBaseComponent base, notnull SCR_MilitaryBaseLogicComponent service)
1352 campaignBase.OnServiceRemoved(service);
1354 SCR_CatalogEntitySpawnerComponent spawner = SCR_CatalogEntitySpawnerComponent.Cast(service);
1359 spawner.GetOnEntitySpawned().Remove(m_Campaign.OnEntityRequested);
1364 void OnDefenderGroupSpawned(notnull SCR_MilitaryBaseLogicComponent service, notnull
SCR_AIGroup group)
1366 SCR_AIGroupUtilityComponent comp = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
1371 ScriptInvokerBase<SCR_AIGroupPerceptionOnEnemyDetectedFiltered> onEnemyDetected = comp.m_Perception.GetOnEnemyDetectedFiltered();
1373 if (!onEnemyDetected)
1376 onEnemyDetected.Insert(OnEnemyDetectedByDefenders);
1378 array<SCR_MilitaryBaseComponent> bases = {};
1379 service.GetBases(bases);
1381 foreach (SCR_MilitaryBaseComponent base : bases)
1388 campaignBase.SetDefendersGroup(group);
1393 void OnConflictStarted()
1400 m_Campaign = campaign;
1409 m_Campaign.GetOnStarted().Insert(OnConflictStarted);
1425 m_Campaign.GetOnStarted().Remove(OnConflictStarted);
1430 enum SCR_ECampaignHQRadioComms