Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIGroup.c
Go to the documentation of this file.
1//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
2
5
6void ScriptInvokerGroupRoleMethod(int groupID, SCR_EGroupRole groupRole);
8typedef ScriptInvokerBase<ScriptInvokerGroupRoleMethod> ScriptInvokerGroupRole;
9
10[EntityEditorProps(category: "GameScripted/AI")]
12{
20 static int GetMembers(IEntitySource entitySource, out array<ResourceName> outPrefabs, out array<vector> outOffsets)
21 {
22 //--- Not a group
23 if (!entitySource || !entitySource.GetClassName().ToType().IsInherited(SCR_AIGroup)) return false;
24
25 ArmaReforgerScripted game = GetGame();
26 if (!game) return 0;
27
28 AIWorld aiWorld = game.GetAIWorld();
29 if (!aiWorld) return 0;
30
31 //--- Get formation
32 AIFormationDefinition formation;
33 IEntityComponentSource componentSource;
34 for (int i = 0, count = entitySource.GetComponentCount(); i < count; i++)
35 {
36 componentSource = entitySource.GetComponent(i);
37 if (componentSource.GetClassName().ToType().IsInherited(AIFormationComponent))
38 {
39 string formationName;
40 componentSource.Get("DefaultFormation", formationName);
41 formation = aiWorld.GetFormation(formationName);
42 break;
43 }
44 }
45 if (!formation) return 0;
46
47 //--- Get member prefabs
48 entitySource.Get("m_aUnitPrefabSlots", outPrefabs);
49
50 //--- Get offsets
51 outOffsets.Clear();
52 int count = outPrefabs.Count();
53 for (int i = 0; i < count; i++)
54 {
55 outOffsets.Insert(formation.GetOffsetPosition(i));
56 }
57
58 return count;
59 }
60}
61
62class SCR_AIGroup_DelayedSpawn
63{
65 int index;
68}
69
72typedef ScriptInvokerBase<ScriptInvoker_AIGroupOnEmpty_Callback> ScriptInvoker_AIGroupOnEmpty;
73
74class SCR_AIGroup : ChimeraAIGroup
75{
76 [Attribute("", UIWidgets.EditBox, "Faction", category: "Group")]
77 string m_faction;
78
79 [Attribute(uiwidget: UIWidgets.ResourceAssignArray, desc: "Entities in group non-ai included", params: "et", category: "Group Members")]
80 ref array<ResourceName> m_aUnitPrefabSlots;
81
82 [Attribute(defvalue: "1", desc: "When true, group members will be spawned above terrain, offset by group's ATL height.\nWhen false, group members will be levelled horizontally with the group.", category: "Group Members")]
83 private bool m_bSnapToTerrain;
84
85 [Attribute("", UIWidgets.EditBox, "List of Waypoint names found in the level", category: "Group Waypoints")]
86 ref array<string> m_aStaticWaypoints;
87
88 [Attribute(defvalue: "", UIWidgets.Object, desc: "Waypoints that should be spawned from prefabs", category: "Group Waypoints")]
89 ref array<ref SCR_WaypointPrefabLocation> m_aSpawnedWaypoints;
90
91 [Attribute(defvalue: "", UIWidgets.EditBox, desc: "List of vehicles to use for movement", category: "Group Vehicles")]
92 ref array<string> m_aStaticVehicles;
93
94 [Attribute(defvalue: "1", desc: "When true, group members will be spawned durin OnInit, if false spawning must be called manually calling SpawnUnits()", category: "Group Members")]
95 private bool m_bSpawnImmediately;
96
97 [Attribute(defvalue: "0", UIWidgets.EditBox, desc: "Delay between spawns of individual members (ms)", category: "Group Members")]
98 protected int m_fMemberSpawnDelay;
99
100 [Attribute(defvalue: "1", UIWidgets.EditBox, desc: "When enabled, the group will be deleted when its last member dies or is deleted.\nThis will *not* delete the group when it starts empty.", category: "Group")]
101 protected bool m_bDeleteWhenEmpty;
102
103 protected static bool s_bIgnoreSnapToTerrain;
104 protected static bool s_bIgnoreSpawning;
105
106 protected ref array<IEntity> m_aSceneGroupUnitInstances;
107 protected ref array<IEntity> m_aSceneWaypointInstances;
108 protected ref array<BaseCompartmentSlot> m_aAllocatedCompartments = {}; // allocated components (on vehicles) this group wants to get in
109 protected ref array<AISmartActionComponent> m_aAllocatedComponents = {}; // allocated smart action components this group wants to use
110
111 protected int m_iMaxUnitsToSpawn = int.MAX;
123
125
127
128 protected ref array<int> m_aAgentIDQueue = {};
129
130 //player groups variables
131 [Attribute(category: "Player settings")]
133
134 [Attribute("1", desc: "Max number of players in this group where 0 means infinite members", category: "Player settings", params: "0 100 1")]
135 protected int m_iMaxMembers;
136
137 [Attribute("0", desc: "Can players join this group?", category: "Player settings")]
138 protected bool m_bPlayable, m_bPrivate;
139
140 [Attribute("1", desc: "Does this group get deleted when empty?", category: "Player settings")]
141 protected bool m_bDeleteIfNoPlayer;
142
143 protected int m_iGroupID = -1;
144 protected int m_iLeaderID = -1;
147 protected bool m_bIsPrivacyChangeable = 1;
150
151 //gamecode uses 0 as invalid playerID
152 protected int m_iDescriptionAuthorID = 0;
153 protected int m_iNameAuthorID = 0;
155
156 protected string m_sCustomName = "";
157 protected string m_sCustomDescription = "";
158 protected ref array<int> m_aPlayerIDs = {};
159 protected static ref ScriptInvoker s_OnPlayerAdded = new ScriptInvoker();
160 protected static ref ScriptInvoker s_OnPlayerRemoved = new ScriptInvoker();
167 protected static ref ScriptInvoker s_OnFlagSelected = new ScriptInvoker();
172 protected static ref ScriptInvokerBase<ScriptInvokerAIGroup> s_OnGroupRallyPointChanged;
173
176
177 protected ref array<int> m_aRequesterIDs = {};
178 protected ref array<int> m_aDeniedRequesters = {};
179
180 [RplProp()]
181 protected int m_iDeployedRadioCount = 0;
182
183 protected int m_RallyPointId = -1;
184 protected bool m_bForcedRallyPoint;
185
186 //commanding variables
189 protected ref array<SCR_ChimeraCharacter> m_aAIMembers = {};
193
194 // entity spawn list
195 protected ref array<ref SCR_AIGroup_DelayedSpawn> m_delayedSpawnList = {};
196 protected ref ScriptInvokerBase<ScriptInvokerAIGroup> Event_OnAllDelayedEntitySpawned;
197
198 protected SCR_ECharacterRank m_eRequiredRank;
199
200 //------------------------------------------------------------------------------------------------
201 //Returns number of AI's that still have to be spawned
203 {
204 return m_delayedSpawnList.Count();
205 }
206
207 //------------------------------------------------------------------------------------------------
212
213 //------------------------------------------------------------------------------------------------
218
219 //------------------------------------------------------------------------------------------------
221 {
222 m_iNumOfMembersToSpawn = number;
223 }
224
225 //------------------------------------------------------------------------------------------------
229 void SetRallyPoint(notnull SCR_MilitaryBaseComponent base, bool force = false)
230 {
231 if (!force && m_bForcedRallyPoint)
232 return;
233
234 int baseCallsign = base.GetCallsign();
235
236 RpcDo_SetRallyPoint(baseCallsign, force);
237 Rpc(RpcDo_SetRallyPoint, baseCallsign, force);
238 }
239
240 //------------------------------------------------------------------------------------------------
247
248 //------------------------------------------------------------------------------------------------
251 {
252 return m_RallyPointId;
253 }
254
255 //------------------------------------------------------------------------------------------------
258 {
259 return m_bForcedRallyPoint;
260 }
261
262 //------------------------------------------------------------------------------------------------
263 protected override void EOnFrame(IEntity owner, float timeSlice)
264 {
265 // No more entities in the list? Turn off frame events
266 if (m_delayedSpawnList.IsEmpty())
267 {
269 return;
270 }
271
272 // Spawn a singular AI entity this frame
273 int spawnIndex = m_delayedSpawnList.Count() - 1;
274 if (SpawnDelayedGroupMember(spawnIndex))
275 m_delayedSpawnList.Remove(spawnIndex);
276
277 // Notify all delayed spawning is done
280 }
281
282 //------------------------------------------------------------------------------------------------
283 /*
284 Returns false when member couldn't be spawned but we should try again
285 True otherwise
286 */
287 bool SpawnDelayedGroupMember(int spawnIndex)
288 {
289 return SpawnGroupMember(
290 m_delayedSpawnList.Get(spawnIndex).snapToTerrain,
291 m_delayedSpawnList.Get(spawnIndex).index,
292 m_delayedSpawnList.Get(spawnIndex).resourceName,
293 m_delayedSpawnList.Get(spawnIndex).editMode,
294 spawnIndex == 0 // isLast
295 );
296 }
297
298 //------------------------------------------------------------------------------------------------
300 {
301 for (int spawnIndex = m_delayedSpawnList.Count() - 1; spawnIndex >= 0; spawnIndex--)
302 SpawnDelayedGroupMember(spawnIndex);
303
304 m_delayedSpawnList.Clear();
305 }
306
307 //------------------------------------------------------------------------------------------------
310 {
311 return !m_delayedSpawnList.IsEmpty();
312 }
313
314 //------------------------------------------------------------------------------------------------
316 {
317 SetEventMask(EntityEvent.FRAME);
318 DeactivateAI();
319
320 // Allow this entity to frame/tick while in Game Master Mode
321 ChimeraWorld world = GetGame().GetWorld();
322 if (world)
323 world.RegisterEntityToBeUpdatedWhileGameIsPaused(this);
324 }
325
326 //------------------------------------------------------------------------------------------------
328 {
329 ClearEventMask(EntityEvent.FRAME);
331 GetGame().GetCallqueue().CallLater(SCR_EntityHelper.DeleteEntityAndChildren, 1, false, this);
332 else if (!m_bPlayable && !IsSlave())
333 ActivateAI();
334
335 ChimeraWorld world = GetGame().GetWorld();
336 if (world)
337 world.UnregisterEntityToBeUpdatedWhileGameIsPaused(this);
338 }
339
340 //------------------------------------------------------------------------------------------------
341 bool HasRequesterID(int id)
342 {
343 return m_aRequesterIDs.Contains(id);
344 }
345
346 //------------------------------------------------------------------------------------------------
347 void RemoveRequester(int playerID)
348 {
349 if (!m_aRequesterIDs.Contains(playerID))
350 return;
351
352 RPC_DoRemoveRequester(playerID);
353 Rpc(RPC_DoRemoveRequester, playerID);
354 if (!m_aRequesterIDs.IsEmpty())
355 return;
356
358 if (gameMode)
359 gameMode.GetOnPlayerDisconnected().Remove(OnPlayerLeftGame);
360 }
361
362 //------------------------------------------------------------------------------------------------
363 int GetDeniedRequesters(out array<int> valueArray)
364 {
365 return valueArray.Copy(m_aDeniedRequesters);
366 }
367
368 //------------------------------------------------------------------------------------------------
369 void AddDeniedRequester(int playerID)
370 {
371 if (m_aDeniedRequesters.Contains(playerID))
372 return;
373
374 RPC_DoAddDeniedRequester(playerID);
375 Rpc(RPC_DoAddDeniedRequester, playerID);
376 }
377
378 //------------------------------------------------------------------------------------------------
384
385 //------------------------------------------------------------------------------------------------
391
392 //------------------------------------------------------------------------------------------------
393 int GetRequesterIDs(out array<int> valueArray)
394 {
395 return valueArray.Copy(m_aRequesterIDs);
396 }
397
398 //------------------------------------------------------------------------------------------------
399 void AddRequester(int playerID)
400 {
401 if (m_aRequesterIDs.Contains(playerID))
402 return;
403
404 if (m_aRequesterIDs.IsEmpty())
405 {
407 if (gameMode)
408 gameMode.GetOnPlayerDisconnected().Insert(OnPlayerLeftGame);
409 }
410
411 RPC_DoAddRequester(playerID);
412 Rpc(RPC_DoAddRequester, playerID);
413 }
414
415 //------------------------------------------------------------------------------------------------
416 void SetFlagIsFromImageSet(bool value)
417 {
418 if (!m_UiInfo)
420
421 m_UiInfo.SetFlagIsFromImageSet(value);
422 }
423
424 //------------------------------------------------------------------------------------------------
426 {
427 if (!m_UiInfo)
429
430 m_UiInfo.SetGroupFlag(flag);
431 }
432
433 //------------------------------------------------------------------------------------------------
435 {
436 if (!m_UiInfo)
438
439 bool flagIsFromSet = m_UiInfo.GetFlagIsFromImageSet();
440 return flagIsFromSet;
441 }
442
443 //------------------------------------------------------------------------------------------------
445 {
446 if (!m_UiInfo)
448
449 ResourceName name = m_UiInfo.GetGroupFlag();
450 return name;
451 }
452
453 //------------------------------------------------------------------------------------------------
455 {
456 return s_OnFlagSelected;
457 }
458
459 //------------------------------------------------------------------------------------------------
464
465 //------------------------------------------------------------------------------------------------
470
471 //------------------------------------------------------------------------------------------------
476
477 //------------------------------------------------------------------------------------------------
478 static ScriptInvokerBase<ScriptInvokerAIGroup> GetOnGroupRallyPointChanged()
479 {
481 s_OnGroupRallyPointChanged = new ScriptInvokerBase<ScriptInvokerAIGroup>();
482
484 }
485
486 //------------------------------------------------------------------------------------------------
487 bool IsPlayerInGroup(int playerID)
488 {
489 return m_aPlayerIDs.Contains(playerID);
490 }
491
492 //------------------------------------------------------------------------------------------------
493 bool IsPlayerLeader(int playerID)
494 {
495 return playerID == m_iLeaderID;
496 }
497
498 //------------------------------------------------------------------------------------------------
500 {
501 return m_iLeaderID;
502 }
503
504 //------------------------------------------------------------------------------------------------
508 {
509 if (m_iLeaderID > 0)
510 return m_iLeaderID;
511
512 if (!GetMaster())
513 return -1;
514
515 return m_MasterGroup.GetFirstPlayerLeaderID();
516 }
517
518 //------------------------------------------------------------------------------------------------
523
524 //------------------------------------------------------------------------------------------------
526 {
528 return;
529
531 }
532
533 //------------------------------------------------------------------------------------------------
535 void SetPrivate(bool isPrivate)
536 {
537 RPC_SetPrivate(isPrivate);
538 Rpc(RPC_SetPrivate, isPrivate);
539 }
540
541 //------------------------------------------------------------------------------------------------
543 {
544 return m_bPrivate;
545 }
546
547 //------------------------------------------------------------------------------------------------
553
554 //------------------------------------------------------------------------------------------------
556 {
558 }
559
560 //------------------------------------------------------------------------------------------------
562 {
563 RpcDo_SetGroupRole(groupRole);
564 Rpc(RpcDo_SetGroupRole, groupRole);
565 }
566
567 //------------------------------------------------------------------------------------------------
569 {
570 return m_eGroupRole;
571 }
572
573 //------------------------------------------------------------------------------------------------
576 {
577 SCR_Faction scrFaction = SCR_Faction.Cast(GetFaction());
578 if (!scrFaction)
579 return string.Empty;
580
581 array<SCR_GroupRolePresetConfig> groupRolePresets = {};
582 scrFaction.GetGroupRolePresetConfigs(groupRolePresets);
583
584 // find preset by group role
585 foreach (SCR_GroupRolePresetConfig preset : groupRolePresets)
586 {
587 if (!preset || preset.GetGroupRole() != m_eGroupRole)
588 continue;
589
590 if (preset.GetGroupRoleName().IsEmpty())
591 return SCR_Enum.GetEnumName(SCR_EGroupRole, preset.GetGroupRole());
592 else
593 return preset.GetGroupRoleName();
594 }
595
596 return string.Empty;
597 }
598
599 //------------------------------------------------------------------------------------------------
602 {
603 return m_bDeleteIfNoPlayer;
604 }
605
606 //------------------------------------------------------------------------------------------------
608 void SetCanDeleteIfNoPlayer(bool deleteEmpty)
609 {
610 m_bDeleteIfNoPlayer = deleteEmpty;
611 }
612
613 //------------------------------------------------------------------------------------------------
614 bool IsFull()
615 {
616 return (IsMaxMembersLimited() && m_iMaxMembers <= m_aPlayerIDs.Count());
617 }
618
619 //------------------------------------------------------------------------------------------------
620 bool IsSlave()
621 {
622 if (!m_MasterGroup && (!m_MasterGroupID || !m_MasterGroupID.IsValid()))
623 return false;
624 return true;
625 }
626
627 //------------------------------------------------------------------------------------------------
633 int GetPlayerAndAgentCount(bool checkMasterAndSlaves = false)
634 {
635 if (!checkMasterAndSlaves)
636 return GetPlayerCount() + GetAgentsCount();
637
638 //~ Return count of group and master and slave groups
640 }
641
642 //------------------------------------------------------------------------------------------------
647 {
648 int totalAgentCount = GetAgentsCount();
649
650 SCR_AIGroup aiGroup = GetSlave();
651 if (aiGroup)
652 totalAgentCount += aiGroup.GetAgentsCount();
653
654 aiGroup = GetMaster();
655 if (aiGroup)
656 totalAgentCount += aiGroup.GetAgentsCount();
657
658 return totalAgentCount;
659 }
660
661 //------------------------------------------------------------------------------------------------
667 {
668 int totalGroupCount = GetAgentsCount();
669
670 SCR_AIGroup aiGroup = GetSlave();
671 if (aiGroup)
672 totalGroupCount += aiGroup.GetAgentsCount();
673
674 aiGroup = GetMaster();
675 if (aiGroup)
676 totalGroupCount += aiGroup.GetAgentsCount();
677
678 return totalGroupCount;
679 }
680
681 //------------------------------------------------------------------------------------------------
687 {
688 int totalGroupCount = GetPlayerCount();
689
690 SCR_AIGroup aiGroup = GetSlave();
691 if (aiGroup)
692 totalGroupCount += aiGroup.GetPlayerCount();
693
694 aiGroup = GetMaster();
695 if (aiGroup)
696 totalGroupCount += aiGroup.GetPlayerCount();
697
698 return totalGroupCount;
699 }
700
701 //------------------------------------------------------------------------------------------------
703 void SetGroupFlag(int flagIndex, bool isFromImageset)
704 {
705 if (!m_UiInfo)
707
708 RPC_DoSetGroupFlag(flagIndex, isFromImageset);
709 Rpc(RPC_DoSetGroupFlag, flagIndex, isFromImageset);
710 }
711
712 //------------------------------------------------------------------------------------------------
713 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
714 void RPC_DoSetGroupFlag(int flagIndex, bool isFromImageset)
715 {
716 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
717 if (!groupManager)
718 return;
719
720 SCR_Faction scrFaction = SCR_Faction.Cast(GetFaction());
721 if (!scrFaction)
722 return;
723
724 m_UiInfo.SetFlagIsFromImageSet(isFromImageset);
725
726 if (isFromImageset)
727 {
728 if (flagIndex >= 0)
729 m_UiInfo.SetGroupFlag(scrFaction.GetFlagName(flagIndex));
730 }
731 else
732 {
733 array<ResourceName> textures = {};
734 scrFaction.GetGroupFlagTextures(textures);
735
736 if (textures.IsIndexValid(flagIndex))
737 m_UiInfo.SetGroupFlag(textures[flagIndex]);
738 }
739
740 s_OnFlagSelected.Invoke();
741 }
742
743 //------------------------------------------------------------------------------------------------
744 void SetCustomName(string name, int authorID)
745 {
746 RPC_DoSetCustomName(name, authorID);
747 Rpc(RPC_DoSetCustomName, name, authorID);
748 }
749
750 //------------------------------------------------------------------------------------------------
751 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
752 void RPC_DoSetCustomName(string name, int authorID)
753 {
754 if (name.IsEmpty())
755 {
756 m_sCustomName = name;
757 m_iNameAuthorID = authorID;
758 s_OnCustomNameChanged.Invoke(this);
759 return;
760 }
761
762 array<string> textToFilter = {};
763
765 textToFilter.Insert(name);
767
768
769
770 if (!GetGame().GetPlatformService().FilterProfanityAsync(textToFilter, m_ProfanityCallbackName))
771 OnNameFilteredCallback(textToFilter);
772
773 m_iNameAuthorID = authorID;
774
775 }
776
777 void OnNameFilteredCallback(array<string> resultText)
778 {
779 if (GetGame().GetPlatformService().GetLocalPlatformKind() == PlatformKind.XBOX)
780 SCR_ProfaneFilter.ReplaceProfanities(resultText.Get(0), m_sCustomName);
781 else
782 m_sCustomName = resultText.Get(0);
783
784 s_OnCustomNameChanged.Invoke(this);
785 }
786
787 //------------------------------------------------------------------------------------------------
788 static bool DeLocalizeText(out string input)
789 {
790 if (input.IsEmpty())
791 return false;
792 string inputLC = input;
793 inputLC.ToLower();
794
795 string profanity = "#";
796
797 int indexOf = inputLC.IndexOf(profanity);
798 if (indexOf < 0)
799 return false;
800
801 int inputLength = input.Length();
802 int profanityLength = profanity.Length();
803 while (indexOf > -1)
804 {
805 if (indexOf > 0)
806 input = input.Substring(0, indexOf) + input.Substring(indexOf + profanityLength, inputLength - profanityLength - indexOf);
807 else
808 input = input.Substring(profanityLength, inputLength - profanityLength);
809
810 indexOf = inputLC.IndexOfFrom(indexOf + profanityLength, profanity);
811 }
812
813 return true;
814 }
815
816 //------------------------------------------------------------------------------------------------
818 void SetCustomDescription(string desc, int authorID)
819 {
821 Rpc(RPC_DoSetCustomDescription, desc, authorID);
822 }
823
824 //------------------------------------------------------------------------------------------------
825 void SetMaxGroupMembers(int value)
826 {
828 Rpc(RPC_DoSetMaxGroupMembers, value);
829 }
830
831 //------------------------------------------------------------------------------------------------
832 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
834 {
835 m_iMaxMembers = value;
836 }
837
838 //------------------------------------------------------------------------------------------------
839 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
840 void RPC_DoSetCustomDescription(string desc, int authorID)
841 {
842 if (desc.IsEmpty())
843 {
845 m_iDescriptionAuthorID = authorID;
846 s_OnCustomDescChanged.Invoke(this);
847 return;
848 }
849
850 array<string> textToFilter = {};
851
853 textToFilter.Insert(desc);
855
856 if (!GetGame().GetPlatformService().FilterProfanityAsync(textToFilter, m_ProfanityCallbackDesc))
857 OnDescFilteredCallback(textToFilter);
858
859 m_iDescriptionAuthorID = authorID;
860 }
861
862 void OnDescFilteredCallback(array<string> resultText)
863 {
864 if (GetGame().GetPlatformService().GetLocalPlatformKind() == PlatformKind.XBOX)
865 SCR_ProfaneFilter.ReplaceProfanities(resultText.Get(0), m_sCustomDescription);
866 else
867 m_sCustomDescription = resultText.Get(0);
868
869 s_OnCustomDescChanged.Invoke();
870 }
871
872 //------------------------------------------------------------------------------------------------
874 {
875 const PlayerController playerController = GetGame().GetPlayerController();
876 if (playerController)
877 {
878 const SocialComponent socialComp = SocialComponent.Cast(playerController.FindComponent(SocialComponent));
879 if (socialComp.IsRestricted(m_iDescriptionAuthorID, EUserInteraction.UserGeneratedContent))
880 return string.Empty;
881 }
882
884 }
885
886 //------------------------------------------------------------------------------------------------
888 {
889 const PlayerController playerController = GetGame().GetPlayerController();
890 if (playerController)
891 {
892 const SocialComponent socialComp = SocialComponent.Cast(playerController.FindComponent(SocialComponent));
893 if (socialComp.IsRestricted(m_iNameAuthorID, EUserInteraction.UserGeneratedContent))
894 return string.Empty;
895 }
896
897 return m_sCustomName;
898 }
899
900 //------------------------------------------------------------------------------------------------
902 {
904 }
905
906 //------------------------------------------------------------------------------------------------
908 {
909 return m_iNameAuthorID;
910 }
911
912 //------------------------------------------------------------------------------------------------
914 {
915 string company, platoon, squad, character, format;
916 GetCallsigns(company, platoon, squad, character, format);
917 string originalName = string.Format(format, company, platoon, squad, character);
918
919 // added check for player controller, because playercontroler is not on dedicated server
920 const PlayerController playerController = GetGame().GetPlayerController();
921 if (!playerController)
922 return originalName;
923
924 const SocialComponent socialComp = SocialComponent.Cast(playerController.FindComponent(SocialComponent));
925 if (!socialComp)
926 return originalName;
927
928 if (m_sCustomName.IsEmpty() || socialComp.IsRestricted(m_iNameAuthorID, EUserInteraction.UserGeneratedContent))
929 return originalName;
930
931 return m_sCustomName + " ( " + originalName + " )";
932 }
933
934 //------------------------------------------------------------------------------------------------
936 {
937 return m_iGroupID;
938 }
939
940 //------------------------------------------------------------------------------------------------
941 void SetGroupID(int id)
942 {
943 m_iGroupID = id;
944 }
945
946 //------------------------------------------------------------------------------------------------
948 {
949 return m_iMaxMembers;
950 }
951
952 //------------------------------------------------------------------------------------------------
954 {
955 return m_iMaxMembers != 0; // 0 means infinite members
956 }
957
958 //------------------------------------------------------------------------------------------------
960 void SetMaxMembers(int maxMembers)
961 {
962 if (maxMembers == GetMaxMembers())
963 return;
964
965 RPC_DoSetMaxMembers(maxMembers);
966 Rpc(RPC_DoSetMaxMembers, maxMembers);
967 }
968
969 //------------------------------------------------------------------------------------------------
970 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
971 void RPC_DoSetMaxMembers(int maxMembers)
972 {
973 m_iMaxMembers = maxMembers;
974 s_OnMaxMembersChanged.Invoke();
975 }
976
977 //------------------------------------------------------------------------------------------------
978 array<int> GetPlayerIDs()
979 {
980 return m_aPlayerIDs;
981 }
982
983 //------------------------------------------------------------------------------------------------
989 int GetPlayerCount(bool checkMasterAndSlaves = false)
990 {
991 if (!checkMasterAndSlaves)
992 return m_aPlayerIDs.Count();
993
994 int totalPlayerCount = GetPlayerCount();
995 SCR_AIGroup aiGroup = GetSlave();
996 if (aiGroup)
997 totalPlayerCount += aiGroup.GetPlayerCount();
998
999 aiGroup = GetMaster();
1000 if (aiGroup)
1001 totalPlayerCount += aiGroup.GetPlayerCount();
1002
1003 return totalPlayerCount;
1004 }
1005
1006 //------------------------------------------------------------------------------------------------
1008 SCR_ECharacterRank GetRequiredRank()
1009 {
1010 return m_eRequiredRank;
1011 }
1012
1013 //------------------------------------------------------------------------------------------------
1015 void SetRequiredRank(SCR_ECharacterRank rank)
1016 {
1017 if (rank == m_eRequiredRank)
1018 return;
1019
1021 Rpc(RpcDo_SetRequiredRank, rank);
1022 }
1023
1024 //------------------------------------------------------------------------------------------------
1025 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1026 void RpcDo_SetRequiredRank(SCR_ECharacterRank rank)
1027 {
1028 m_eRequiredRank = rank;
1029 }
1030
1031 //------------------------------------------------------------------------------------------------
1033 {
1035 }
1036
1037 //------------------------------------------------------------------------------------------------
1038 void SetCreatedByCommander(bool isCreatedByCommander)
1039 {
1040 RpcDo_SetCreatedByCommander(isCreatedByCommander);
1041 Rpc(RpcDo_SetCreatedByCommander, isCreatedByCommander);
1042 }
1043 //------------------------------------------------------------------------------------------------
1045 {
1046 return m_rPreset;
1047 }
1048
1049 //------------------------------------------------------------------------------------------------
1051 {
1052 m_rPreset = preset;
1053 }
1054
1055 //------------------------------------------------------------------------------------------------
1056 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1057 void RpcDo_SetCreatedByCommander(bool isCreatedByCommander)
1058 {
1059 m_bIsCreatedByCommander = isCreatedByCommander;
1060 }
1061
1062 //------------------------------------------------------------------------------------------------
1070
1071 //------------------------------------------------------------------------------------------------
1073 {
1074 return s_OnPlayerAdded;
1075 }
1076
1077 //------------------------------------------------------------------------------------------------
1079 {
1080 return s_OnPlayerRemoved;
1081 }
1082
1083 //------------------------------------------------------------------------------------------------
1088
1089 //------------------------------------------------------------------------------------------------
1094
1095 //------------------------------------------------------------------------------------------------
1100
1101 //------------------------------------------------------------------------------------------------
1103 {
1104 return s_OnFrequencyChanged;
1105 }
1106
1107 //------------------------------------------------------------------------------------------------
1112
1113 //------------------------------------------------------------------------------------------------
1121
1122 //------------------------------------------------------------------------------------------------
1123 void AddAgentFromControlledEntity(notnull IEntity controlledEntity)
1124 {
1125 AIControlComponent aiControlComponent = AIControlComponent.Cast(controlledEntity.FindComponent(AIControlComponent));
1126 if (!aiControlComponent)
1127 return;
1128
1129 AIAgent agent = aiControlComponent.GetAIAgent();
1130 if (!agent)
1131 return;
1132
1133 AddAgent(agent);
1134
1135 //we send notification to master group players
1136 if (IsSlave())
1137 NotificateGroupAIChange(controlledEntity, ENotification.GROUPS_AI_JOINED);
1138
1140 }
1141
1142 //------------------------------------------------------------------------------------------------
1143 void RemoveAgentFromControlledEntity(notnull IEntity controlledEntity)
1144 {
1145 AIControlComponent aiControlComponent = AIControlComponent.Cast(controlledEntity.FindComponent(AIControlComponent));
1146 if (!aiControlComponent)
1147 return;
1148
1149 AIAgent agent = aiControlComponent.GetAIAgent();
1150 if (!agent)
1151 return;
1152 RemoveAgent(agent);
1153
1154 //we send notification to master group players
1155 if (IsSlave())
1156 NotificateGroupAIChange(controlledEntity, ENotification.GROUPS_AI_LEFT);
1157
1159 }
1160
1161 //------------------------------------------------------------------------------------------------
1162 void NotificateGroupAIChange(IEntity controlledEntity, ENotification notificationType)
1163 {
1164 RplId rplId = -1;
1166 if (editableEntityComp)
1167 rplId = Replication.FindItemId(editableEntityComp);
1168
1169 if (rplId.IsValid())
1170 SCR_NotificationsComponent.SendToGroup(GetMaster().GetGroupID(), notificationType, rplId);
1171 }
1172
1173 //------------------------------------------------------------------------------------------------
1175 void OnPlayerDisconnected(int playerID)
1176 {
1177 // No need to null check m_aPlayerIDs, it always exists together with this entity
1178 int index = m_aPlayerIDs.Find(playerID);
1179 if (index < 0)
1180 return;
1181
1182 SCR_GroupsManagerComponent groupsManager = SCR_GroupsManagerComponent.GetInstance();
1183 if (groupsManager)
1184 groupsManager.AddDisconnectedPlayer(playerID, m_iGroupID);
1185
1186 RemovePlayer(playerID);
1187 }
1188
1189 //------------------------------------------------------------------------------------------------
1190 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1192 {
1194 GetGame().GetCallqueue().CallLater(Event_OnGroupMemberStateChange.Invoke, 1, false, null, null, null, null, null, null, null, null, null);
1195 }
1196
1197 //------------------------------------------------------------------------------------------------
1200 {
1201 RPC_DoOnGroupMemberStateChange(); //Local call
1202 Rpc(RPC_DoOnGroupMemberStateChange); //Broadcast to clients
1203 }
1204
1205 //------------------------------------------------------------------------------------------------
1206 void OnMemberDeath(notnull SCR_CharacterControllerComponent memberController, IEntity killerEntity, Instigator killer)
1207 {
1208 //This event is only called for members of the group, so it's safe to call QueueAddAgent automatically
1209 int playerID = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(memberController.GetCharacter());
1210 QueueAddAgent(playerID);
1211 RemovePlayerAgent(playerID);
1213 }
1214
1215 //------------------------------------------------------------------------------------------------
1216 void ListenToMemberDeath(notnull IEntity groupMember)
1217 {
1218 SCR_CharacterControllerComponent characterController = SCR_CharacterControllerComponent.Cast(groupMember.FindComponent(SCR_CharacterControllerComponent));
1219 if (!characterController)
1220 return;
1221
1222 characterController.GetOnPlayerDeathWithParam().Insert(OnMemberDeath);
1223 }
1224
1225 //------------------------------------------------------------------------------------------------
1226 void AddOnGadgetsLoadedListener(int playerID, notnull IEntity controlledEntity)
1227 {
1229
1231 if (gameMode)
1233 }
1234
1235 //------------------------------------------------------------------------------------------------
1236 void OnControllableEntitySpawned(IEntity controlledEntity, notnull SCR_GadgetManagerComponent gadgetManager)
1237 {
1238 if (!controlledEntity)
1239 return;
1240
1241 int playerID = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(controlledEntity);
1242 if (playerID == 0)
1243 return;
1244
1245 int index = m_aAgentIDQueue.Find(playerID);
1246 if (index < 0)
1247 return;
1248
1249 ListenToMemberDeath(controlledEntity);
1250 AddAgentFromControlledEntity(controlledEntity);
1251 m_aAgentIDQueue.Remove(index);
1252
1253 if (!m_aAgentIDQueue.IsEmpty())
1254 return;
1255
1257 }
1258
1259 //------------------------------------------------------------------------------------------------
1260 void QueueAddAgent(int playerID)
1261 {
1262 // Avoiding duplicate entries
1263 m_aAgentIDQueue.Insert(playerID);
1264 if (m_aAgentIDQueue.Count() != 1)
1265 return;
1266
1268 if (!gameMode)
1269 return;
1270
1271 // Waiting for spawn of a controllable entity with correct ID
1273 }
1274
1275 //------------------------------------------------------------------------------------------------
1276 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1277 void RPC_DoAddPlayer(int playerID)
1278 {
1279 m_aPlayerIDs.Insert(playerID);
1280 s_OnPlayerAdded.Invoke(this, playerID);
1281 }
1282
1283 //------------------------------------------------------------------------------------------------
1286 void CheckForLeader(int playerID, bool noLeaderAllowed)
1287 {
1288 //check if leader is still in group, noleaderallowed is preparation for editor integration
1289 if (!IsPlayerInGroup(GetLeaderID()) && !noLeaderAllowed && playerID == -1)
1290 {
1291 if (m_aPlayerIDs.IsEmpty())
1292 {
1293 SetCustomName("", 0);
1294 SetCustomDescription("", 0);
1295
1297 return;
1298 }
1300 return;
1301 }
1302
1303 //if we have a leader, do nothing
1304 if (GetLeaderID() != -1)
1305 return;
1306
1307 //otherwise appoint provided player as a leader
1308 if (playerID != -1)
1309 SetGroupLeader(playerID);
1310
1311
1312 }
1313
1314 //------------------------------------------------------------------------------------------------
1316 void SetGroupLeader(int playerID)
1317 {
1318 //reset custom name and description on leader change
1319 if (GetNameAuthorID() != playerID)
1320 SetCustomName("", 0);
1321
1322 if (GetDescriptionAuthorID() != playerID)
1323 SetCustomDescription("", 0);
1324
1325 SCR_NotificationsComponent.SendToGroup(m_iGroupID, ENotification.GROUPS_PLAYER_PROMOTED_LEADER, playerID);
1326 RPC_SetLeaderID(playerID);
1327 Rpc(RPC_SetLeaderID, playerID);
1328 }
1329
1330 //------------------------------------------------------------------------------------------------
1331 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1332 void RPC_SetLeaderID(int playerID)
1333 {
1334 if (playerID == m_iLeaderID)
1335 return;
1336 m_iLeaderID = playerID;
1337 s_OnPlayerLeaderChanged.Invoke(m_iGroupID, playerID);
1338 }
1339
1340 //------------------------------------------------------------------------------------------------
1341 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1342 void RPC_SetPrivate(bool isPrivate)
1343 {
1344 m_bPrivate = isPrivate;
1345 s_OnPrivateGroupChanged.Invoke(m_iGroupID, isPrivate);
1346
1347 if (!isPrivate)
1348 {
1351 }
1352 }
1353
1354 //------------------------------------------------------------------------------------------------
1355 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1360
1361 //------------------------------------------------------------------------------------------------
1362 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1364 {
1365 m_eGroupRole = groupRole;
1366
1368 s_OnGroupRoleChanged.Invoke(m_iGroupID, groupRole);
1369 }
1370
1371 //------------------------------------------------------------------------------------------------
1372 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1373 void RpcDo_SetRallyPoint(int callsignId, bool force)
1374 {
1375 if (m_RallyPointId == callsignId)
1376 {
1378 return;
1379 }
1380
1381 m_RallyPointId = callsignId;
1382 m_bForcedRallyPoint = force;
1383
1385 s_OnGroupRallyPointChanged.Invoke(this);
1386 }
1387
1388 //------------------------------------------------------------------------------------------------
1389 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1391 {
1392 m_RallyPointId = -1;
1393 m_bForcedRallyPoint = false;
1394
1396 s_OnGroupRallyPointChanged.Invoke(this);
1397 }
1398
1399 //------------------------------------------------------------------------------------------------
1401 void AddPlayer(int playerID)
1402 {
1403 // Avoiding duplicate entries
1404 if (m_aPlayerIDs.Contains(playerID))
1405 return;
1406
1407 SCR_NotificationsComponent.SendToGroup(m_iGroupID, ENotification.GROUPS_PLAYER_JOINED, playerID);
1408 RPC_DoAddPlayer(playerID);
1409 Rpc(RPC_DoAddPlayer, playerID);
1410
1411 // Start listening to disconnect events when we add the first player
1412 if (m_aPlayerIDs.Count() == 1)
1413 {
1415 if (gameMode)
1417 }
1418 // Now we need the player character's agent
1419 IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
1420 if (!controlledEntity)
1421 QueueAddAgent(playerID);
1422 else
1423 {
1424 SCR_PlayerController scriptedController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerID));
1425 if (!scriptedController || !scriptedController.IsPossessing())
1426 AddAgentFromControlledEntity(controlledEntity);
1427 }
1428
1429 GetGame().GetCallqueue().CallLater(CheckForLeader, 0, false, playerID, false);
1430 }
1431
1432 //------------------------------------------------------------------------------------------------
1433 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1434 void RPC_DoAddRequester(int playerID)
1435 {
1436 m_aRequesterIDs.Insert(playerID);
1438 }
1439
1440 //------------------------------------------------------------------------------------------------
1441 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1442 void RPC_DoRemoveRequester(int playerID)
1443 {
1444 m_aRequesterIDs.RemoveItem(playerID);
1445 }
1446
1447 //------------------------------------------------------------------------------------------------
1448 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1449 protected void RPC_DoRemoveLeavingPlayer(int playerID)
1450 {
1451 m_aRequesterIDs.RemoveItem(playerID);
1453 }
1454
1455 //------------------------------------------------------------------------------------------------
1458 protected void OnPlayerLeftGame(int playerId)
1459 {
1460 if (!m_aRequesterIDs.Contains(playerId))
1461 return;
1462
1463 RPC_DoRemoveLeavingPlayer(playerId);
1464 Rpc(RPC_DoRemoveLeavingPlayer, playerId);
1465 if (!m_aRequesterIDs.IsEmpty())
1466 return;
1467
1469 if (gameMode)
1470 gameMode.GetOnPlayerDisconnected().Remove(OnPlayerLeftGame);
1471 }
1472
1473 //------------------------------------------------------------------------------------------------
1474 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1476 {
1477 m_aDeniedRequesters.Clear();
1478 }
1479
1480 //------------------------------------------------------------------------------------------------
1481 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1483 {
1484 m_aRequesterIDs.Clear();
1485 }
1486
1487 //------------------------------------------------------------------------------------------------
1488 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1489 void RPC_DoAddDeniedRequester(int playerID)
1490 {
1491 m_aDeniedRequesters.Insert(playerID);
1492 }
1493
1494 //------------------------------------------------------------------------------------------------
1495
1496 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1497 void RPC_DoRemovePlayer(int playerID)
1498 {
1499 m_aPlayerIDs.RemoveItem(playerID);
1500 if (m_iLeaderID == playerID)
1501 m_iLeaderID = -1;
1502
1503 s_OnPlayerRemoved.Invoke(this, playerID);
1504 }
1505
1506 //------------------------------------------------------------------------------------------------
1507 void RemovePlayerAgent(int playerID)
1508 {
1509 IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
1510 if (!controlledEntity)
1511 return;
1512
1513 AIControlComponent aiControlComponent = AIControlComponent.Cast(controlledEntity.FindComponent(AIControlComponent));
1514 if (!aiControlComponent)
1515 return;
1516
1517 AIAgent agent = aiControlComponent.GetAIAgent();
1518 if (!agent)
1519 return;
1520
1521 RemoveAgent(agent);
1522 }
1523
1524 //------------------------------------------------------------------------------------------------
1526 void RemovePlayer(int playerID)
1527 {
1528 if (!m_aPlayerIDs.Contains(playerID))
1529 return;
1530
1531 //if player is last in group it doesnt matter as the group will get deleted
1532 if (playerID == m_iLeaderID && GetPlayerCount() > 1)
1533 {
1534 SetCustomName("", 0);
1535 SetCustomDescription("", 0);
1536 }
1537
1538 RPC_DoRemovePlayer(playerID);
1539 Rpc(RPC_DoRemovePlayer, playerID);
1540 CheckForLeader(-1, false);
1541 RemovePlayerAgent(playerID);
1542 SCR_NotificationsComponent.SendToGroup(m_iGroupID, ENotification.GROUPS_PLAYER_LEFT, playerID);
1543 }
1544
1545 //------------------------------------------------------------------------------------------------
1546 void GetCallsigns(out string company, out string platoon, out string squad, out string character, out string format)
1547 {
1548 SCR_CallsignGroupComponent callsignComponent = SCR_CallsignGroupComponent.Cast(FindComponent(SCR_CallsignGroupComponent));
1549 if (!callsignComponent)
1550 return;
1551
1552 callsignComponent.GetCallsignNames(company, platoon, squad, character, format);
1553 }
1554
1555 //------------------------------------------------------------------------------------------------
1556 void SetRadioFrequency(int frequency)
1557 {
1558 if (frequency == GetRadioFrequency() || frequency <= 0)
1559 return;
1560
1561 RPC_DoSetFrequency(frequency);
1562 Rpc(RPC_DoSetFrequency, frequency);
1563 }
1564
1565 //------------------------------------------------------------------------------------------------
1566 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
1567 void RPC_DoSetFrequency(int frequency)
1568 {
1569 m_iGroupRadioFrequency = frequency;
1570 s_OnFrequencyChanged.Invoke();
1571 }
1572
1573 //------------------------------------------------------------------------------------------------
1575 {
1577 }
1578
1579 //------------------------------------------------------------------------------------------------
1581 {
1582 return m_bPlayable;
1583 }
1584
1585 //------------------------------------------------------------------------------------------------
1586 protected void CreateUnitEntities(bool editMode, array<ResourceName> entityResourceNames)
1587 {
1588 if (!GetGame().GetAIWorld())
1589 {
1590 Print(string.Format("Cannot spawn team members of group %1, AIWorld is missing in the world!", this), LogLevel.WARNING);
1591 return;
1592 }
1593
1594#ifdef WORKBENCH
1595 if (!editMode)
1596 {
1597 //--- Are AI components valid?
1598 AIFormationComponent AIFormation = AIFormationComponent.Cast(FindComponent(AIFormationComponent));
1599
1600 if (!AIFormation)
1601 Print(string.Format("Group %1 does not have AIFormationComponent! Team members will not be spawned.", this), LogLevel.WARNING);
1602 else
1603 {
1604 AIFormationDefinition formationDefinition = AIFormation.GetFormation();
1605 if (!formationDefinition)
1606 Print(string.Format("Formation of group %1 not found in SCR_AIWorld! Team members will not be spawned.", this), LogLevel.WARNING);
1607 }
1608 }
1609#endif
1610 //--- Apply global override
1611 bool snapToTerrain = m_bSnapToTerrain;
1613 {
1614 snapToTerrain = false;
1615 s_bIgnoreSnapToTerrain = false;
1616 }
1617 if (Replication.IsClient())
1618 return;
1619
1620 //--- We are in WB, prepare array so previews can be deleted later
1622 m_aSceneGroupUnitInstances = new array<IEntity>;
1623
1624 m_iNumOfMembersToSpawn = Math.Min(entityResourceNames.Count(), m_iMaxUnitsToSpawn);
1625 //--- Create group members
1626 for (int i = m_iNumOfMembersToSpawn-1; i >= 0; i--)
1627 {
1628 // Spawn group across multiple frames
1629 SCR_AIGroup_DelayedSpawn delaySpawn = new SCR_AIGroup_DelayedSpawn();
1630 delaySpawn.snapToTerrain = snapToTerrain;
1631 delaySpawn.index = i;
1632 delaySpawn.resourceName = entityResourceNames[i];
1633 delaySpawn.editMode = editMode;
1634
1635 m_delayedSpawnList.Insert(delaySpawn);
1636 }
1637
1638 if (editMode)
1639 {
1640 //--- Edit mode has no game world, spawn immediately
1642 }
1643 else
1644 {
1645 //--- Enable the frame event and frames when paused
1647 }
1648
1649 //--- Call group init if it cannot be called by the last spawned entity
1651 Event_OnInit.Invoke(this);
1652 }
1653 /*
1654 Spawn single Group member.
1655 Returns false when action has to be delayed
1656 */
1657 protected bool SpawnGroupMember(bool snapToTerrain, int index, ResourceName res, bool editMode, bool isLast)
1658 {
1659 if (!GetGame().GetAIWorld().CanLimitedAIBeAdded())
1660 {
1661 if (isLast && Event_OnInit)
1662 Event_OnInit.Invoke(this);
1663
1664 //Event_OnLastGroupMemberSpawned.Invoke(this);
1665
1666 return true;
1667 }
1668 BaseWorld world = GetWorld();
1669 AIFormationDefinition formationDefinition;
1670 AIFormationComponent formationComponent = AIFormationComponent.Cast(this.FindComponent(AIFormationComponent));
1671 if (formationComponent)
1672 formationDefinition = formationComponent.GetFormation();
1673 EntitySpawnParams spawnParams = new EntitySpawnParams;
1674 spawnParams.TransformMode = ETransformMode.WORLD;
1675 GetWorldTransform(spawnParams.Transform);
1676 vector pos = spawnParams.Transform[3];
1677
1678 if (formationDefinition)
1679 pos = CoordToParent(formationDefinition.GetOffsetPosition(index));
1680 else
1681 pos = CoordToParent(Vector(index, 0, 0));
1682
1683 if (snapToTerrain)
1684 {
1685 float surfaceY = world.GetSurfaceY(pos[0], pos[2]);
1686 pos[1] = surfaceY;
1687 }
1688
1689
1690 //Snap to the nearest navmesh point
1691 AIPathfindingComponent pathFindindingComponent = AIPathfindingComponent.Cast(this.FindComponent(AIPathfindingComponent));
1692
1693 if (!editMode)
1694 {
1695 NavmeshWorldComponent navmesh = pathFindindingComponent.GetNavmeshComponent();
1696 if (navmesh)
1697 {
1698 if (navmesh.IsTileRequested(pos))
1699 {
1700 return false;
1701 }
1702 if (!navmesh.IsTileLoaded(pos))
1703 {
1704 navmesh.LoadTileIn(pos);
1705 return false;
1706 }
1707 }
1708 }
1709
1710 if (pathFindindingComponent && pathFindindingComponent.GetClosestPositionOnNavmesh(pos, "10 10 10", pos))
1711 {
1712 float groundHeight = world.GetSurfaceY(pos[0], pos[2]);
1713 if (pos[1] < groundHeight)
1714 pos[1] = groundHeight;
1715 vector outWaterSurfacePoint;
1716 EWaterSurfaceType waterSurfaceType;
1717 vector transformWS[4];
1718 vector obbExtents;
1719 if (ChimeraWorldUtils.TryGetWaterSurface(GetWorld(), pos, outWaterSurfacePoint, waterSurfaceType, transformWS, obbExtents))
1720 {
1721 pos = outWaterSurfacePoint;
1722 }
1723 }
1724
1725 spawnParams.Transform[3] = pos;
1726
1727 IEntity member = GetGame().SpawnEntityPrefabEx(res, true, world, spawnParams);
1728 if (!member)
1729 return true;
1730
1731 // Move in to vehicle
1733
1734
1735 if (editMode)
1736 m_aSceneGroupUnitInstances.Insert(member);
1737
1738 // Even same null-check is above, in some situations, member can get deleted and it would result in VME
1739 if (!member)
1740 return true;
1741
1742 AddAIEntityToGroup(member);
1743
1744 FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(member.FindComponent(FactionAffiliationComponent));
1745
1746 if (factionAffiliation)
1747 factionAffiliation.SetAffiliatedFactionByKey(m_faction);
1748
1749 if (isLast && Event_OnInit)
1750 Event_OnInit.Invoke(this);
1751 return true;
1752 }
1753
1754 //------------------------------------------------------------------------------------------------
1755 void SetWaypointParams(out AIWaypoint wp, SCR_WaypointPrefabLocation prefabParams)
1756 {
1757 if (SCR_TimedWaypoint.Cast(wp) && !float.AlmostEqual(prefabParams.m_WPTimeOverride, 0.0))
1758 SCR_TimedWaypoint.Cast(wp).SetHoldingTime(prefabParams.m_WPTimeOverride);
1759 if (!float.AlmostEqual(prefabParams.m_WPRadiusOverride, 0.0))
1760 wp.SetCompletionRadius(prefabParams.m_WPRadiusOverride);
1761 wp.SetName(prefabParams.m_WPInstanceName);
1762 }
1763
1764 //------------------------------------------------------------------------------------------------
1765 void AddWaypointsDynamic(out array<IEntity> entityInstanceList, array<ref SCR_WaypointPrefabLocation> prefabs)
1766 {
1767 entityInstanceList = new array<IEntity>;
1768 EntitySpawnParams spawnParams = new EntitySpawnParams;
1769 spawnParams.TransformMode = ETransformMode.WORLD;
1770 vector mat[4];
1771 Math3D.MatrixIdentity4(mat);
1772 for (int i = 0, length = prefabs.Count(); i < length; i++)
1773 {
1774 IEntity entity;
1775 AIWaypoint wp;
1776 mat[3] = prefabs[i].m_WPWorldLocation;
1777 spawnParams.Transform = mat;
1778
1779#ifdef WORKBENCH //includes game mode run from WB
1780 WorldEditorAPI m_API = _WB_GetEditorAPI();
1781 if (m_API)
1782 {
1783 Print(prefabs[i].m_WPPrefabName);
1784 entity = GetGame().SpawnEntityPrefab(Resource.Load(prefabs[i].m_WPPrefabName), m_API.GetWorld(), spawnParams);
1785 entityInstanceList.Insert(entity);
1786 wp = AIWaypoint.Cast(entity);
1787 }
1788 else
1789 {
1790 entity = GetGame().SpawnEntityPrefab(Resource.Load(prefabs[i].m_WPPrefabName), GetGame().GetWorld(), spawnParams);
1791 wp = AIWaypoint.Cast(entity);
1792 AddWaypoint(wp);
1793 }
1794#else // game run from build
1795 entity = GetGame().SpawnEntityPrefab(Resource.Load(prefabs[i].m_WPPrefabName), GetGame().GetWorld(), spawnParams);
1796 wp = AIWaypoint.Cast(entity);
1797 AddWaypoint(wp);
1798#endif
1799 if (wp)
1800 SetWaypointParams(wp, prefabs[i]);
1801 }
1802 }
1803
1804 //------------------------------------------------------------------------------------------------
1805 void AddWaypointsStatic(array<string> aWaypointNames)
1806 {
1807 for (int i = 0, length = aWaypointNames.Count(); i < length; i++)
1808 {
1809#ifdef WORKBENCH
1810 WorldEditorAPI m_API = _WB_GetEditorAPI();
1811 if (m_API)
1812 {
1813 AddWaypoint(AIWaypoint.Cast(m_API.GetWorld().FindEntityByName(aWaypointNames[i])));
1814 }
1815 else
1816 {
1817 AddWaypoint(AIWaypoint.Cast(GetGame().GetWorld().FindEntityByName(aWaypointNames[i])));
1818 }
1819#else
1820 AddWaypoint(AIWaypoint.Cast(GetGame().GetWorld().FindEntityByName(aWaypointNames[i])));
1821#endif
1822 }
1823 }
1824
1825 //------------------------------------------------------------------------------------------------
1826 void AddVehiclesStatic(array<string> aVehicleNames)
1827 {
1828 for (int i = 0, length = aVehicleNames.Count(); i < length; i++)
1829 {
1830 IEntity vehicle;
1831
1832#ifdef WORKBENCH
1833 WorldEditorAPI m_API = _WB_GetEditorAPI();
1834 if (m_API)
1835 {
1836 vehicle = m_API.GetWorld().FindEntityByName(aVehicleNames[i]);
1837 }
1838 else
1839 {
1840 vehicle = GetGame().GetWorld().FindEntityByName(aVehicleNames[i]);
1841 }
1842#else
1843 vehicle = GetGame().GetWorld().FindEntityByName(aVehicleNames[i]);
1844#endif
1845
1846 if (vehicle)
1847 {
1849 if (vehicleUsageComp)
1850 m_GroupUtilityComponent.m_VehicleMgr.TryAddVehicle(vehicleUsageComp);
1851 }
1852 }
1853 }
1854
1855 //------------------------------------------------------------------------------------------------
1856 protected void DestroyEntities(out array<IEntity> entityList)
1857 {
1858 if (!entityList)
1859 return;
1860
1861 for (int i=0, length = entityList.Count(); i < length; i++)
1862 {
1863 if (AIWaypoint.Cast(entityList[i]))
1864 RemoveWaypointFromGroup(AIWaypoint.Cast(entityList[i]));
1865 else
1866 RemoveAIEntityFromGroup(entityList[i]);
1867 delete entityList[i];
1868 }
1869 entityList.Clear();
1870 entityList = null;
1871 }
1872
1873 //------------------------------------------------------------------------------------------------
1874 void RemoveStaticWaypointRefs(array<string> aWaypointNames)
1875 {
1876 if (!aWaypointNames)
1877 return;
1878
1879 for (int i=0, length = aWaypointNames.Count(); i < length; i++)
1880 {
1881#ifdef WORKBENCH
1882 WorldEditorAPI m_API = _WB_GetEditorAPI();
1883 if (m_API)
1884 {
1885 RemoveWaypointFromGroup(AIWaypoint.Cast(m_API.GetWorld().FindEntityByName(aWaypointNames[i])));
1886 }
1887 else
1888 {
1889 RemoveWaypointFromGroup(AIWaypoint.Cast(GetGame().GetWorld().FindEntityByName(aWaypointNames[i])));
1890 }
1891#else
1892 RemoveWaypointFromGroup(AIWaypoint.Cast(GetGame().GetWorld().FindEntityByName(aWaypointNames[i])));
1893#endif
1894 }
1895 }
1896
1897 //------------------------------------------------------------------------------------------------
1898 void ClearRefs(out array<IEntity> entityList)
1899 {
1900 if (entityList)
1901 entityList.Clear();
1902 entityList = null;
1903 }
1904
1905 //------------------------------------------------------------------------------------------------
1907 {
1908 if (!entity) return false;
1909
1910 AIControlComponent control = AIControlComponent.Cast(entity.FindComponent(AIControlComponent));
1911 if (!control) return false;
1912
1913 AIAgent agent = control.GetControlAIAgent();
1914 if (!agent) return false;
1915
1916 control.ActivateAI();
1917
1918 if (!agent.GetParentGroup())
1919 AddAgent(agent); //--- Add to group only if some other system (e.g., component on the group member) wasn't faster
1920
1921 return true;
1922 }
1923
1924 //------------------------------------------------------------------------------------------------
1926 {
1927#ifdef WORKBENCH
1928 WorldEditorAPI m_API = _WB_GetEditorAPI();
1929 if (!m_API && entity && entity.FindComponent(AIControlComponent))
1930 {
1931 ref AIAgent agent = AIControlComponent.Cast(entity.FindComponent(AIControlComponent)).GetControlAIAgent();
1932 RemoveAgent(agent);
1933 return true;
1934 }
1935#else
1936 if (entity && entity.FindComponent(AIControlComponent))
1937 {
1938 ref AIAgent agent = AIControlComponent.Cast(entity.FindComponent(AIControlComponent)).GetControlAIAgent();
1939 RemoveAgent(agent);
1940 return true;
1941 }
1942#endif
1943 return false;
1944 }
1945
1946 //------------------------------------------------------------------------------------------------
1947 void AddWaypointToGroup(AIWaypoint waypoint)
1948 {
1949 if (waypoint)
1950 {
1951 AddWaypoint(waypoint);
1952 }
1953 }
1954
1955 //------------------------------------------------------------------------------------------------
1956 void RemoveWaypointFromGroup(AIWaypoint waypoint)
1957 {
1958 if (waypoint)
1959 {
1960 RemoveWaypoint(waypoint)
1961 }
1962 }
1963
1964 //------------------------------------------------------------------------------------------------
1965 void GetAllocatedCompartments(out array<BaseCompartmentSlot> allocatedCompartments)
1966 {
1967 allocatedCompartments = m_aAllocatedCompartments;
1968 }
1969
1970 //------------------------------------------------------------------------------------------------
1971 void GetAllocatedSmartActions(out array<AISmartActionComponent> allocatedComponents)
1972 {
1973 allocatedComponents = m_aAllocatedComponents;
1974 }
1975
1976 //------------------------------------------------------------------------------------------------
1977 void AllocateSmartActions(array<AISmartActionComponent> components)
1978 {
1979 if (!components || components.IsEmpty())
1980 return;
1981
1982 foreach (AISmartActionComponent component : components)
1983 {
1984 if (m_aAllocatedComponents.Find(component) > -1)
1985 {
1986 Print("Trying to allocate same component twice!", LogLevel.WARNING);
1987 continue;
1988 };
1989 m_aAllocatedComponents.Insert(component);
1990 component.SetActionAccessible(false);
1991 }
1992 }
1993
1994 //------------------------------------------------------------------------------------------------
1996 {
1997 if (!compartment)
1998 return;
1999 if (m_aAllocatedCompartments.Find(compartment) > -1)
2000 {
2001 Print("Trying to allocate same compartment twice!", LogLevel.WARNING);
2002 return;
2003 };
2004 if (!compartment.IsCompartmentAccessible())
2005 {
2006 Print("Compartment already reserved!", LogLevel.WARNING);
2007 return;
2008 };
2009 compartment.SetCompartmentAccessible(false);
2010 m_aAllocatedCompartments.Insert(compartment);
2011 }
2012
2013 //------------------------------------------------------------------------------------------------
2015 {
2016 int index = m_aAllocatedCompartments.Find(compartment);
2017 if (index > -1)
2019 else
2020 Print("Trying to remove compartment that is not allocated!", LogLevel.WARNING);
2021 }
2022
2023 //------------------------------------------------------------------------------------------------
2025 {
2027 {
2028 if (comp)
2029 comp.SetCompartmentAccessible(true);
2030 }
2032 }
2033
2034 //------------------------------------------------------------------------------------------------
2036 {
2037 int index = m_aAllocatedComponents.Find(component);
2038 if (index > -1)
2040 else
2041 Print("Trying to remove smart action that is not allocated!", LogLevel.WARNING);
2042 }
2043
2044 //------------------------------------------------------------------------------------------------
2046 {
2048 {
2049 if (comp)
2050 comp.SetActionAccessible(true);
2051 }
2052 m_aAllocatedComponents.Clear();
2053 }
2054
2055 //------------------------------------------------------------------------------------------------
2061 bool InitFactionKey(string factionKey)
2062 {
2063 if (m_faction != "") return false;
2064 m_faction = factionKey;
2065 return true;
2066 }
2067
2068 //------------------------------------------------------------------------------------------------
2075 bool SetFaction(Faction faction)
2076 {
2077 if (Replication.IsClient())
2078 return false;
2079
2080 // If playable, we don't want to allow changing the faction.
2081 if (m_bPlayable && m_faction)
2082 return false;
2083
2084 if (!faction)
2085 return false;
2086
2087 m_faction = faction.GetFactionKey();
2088
2089 array<AIAgent> agents = new array<AIAgent>;
2090 GetAgents(agents);
2091 array<IEntity> updatedVehicles = new array<IEntity>;
2092 //array<RplId> entitiesInVehiclesIds = new array<RplId>;
2093 IEntity vehicle;
2094 IEntity charEntity;
2095
2096 foreach (AIAgent agent : agents)
2097 {
2098 charEntity = agent.GetControlledEntity();
2099
2100 if (!charEntity)
2101 continue;
2102
2103 FactionAffiliationComponent factionAffiliation = FactionAffiliationComponent.Cast(charEntity.FindComponent(FactionAffiliationComponent));
2104 if (factionAffiliation)
2105 factionAffiliation.SetAffiliatedFaction(faction);
2106 }
2107
2108 //Send out event
2110 Event_OnFactionChanged.Invoke(faction);
2111
2112 FactionManager factionManager = GetGame().GetFactionManager();
2113 int factionIndex = factionManager.GetFactionIndex(faction);
2114 if (factionManager)
2115 GetGame().GetCallqueue().CallLater(SetFactionDelayed, 1, false, factionIndex);
2116
2117 return true;
2118 }
2119
2120 //------------------------------------------------------------------------------------------------
2121 protected void SetFactionDelayed(int factionIndex)
2122 {
2123 Rpc(BroadCastSetFaction, factionIndex);
2124 }
2125
2126 //------------------------------------------------------------------------------------------------
2127 //Send to update Editor UI
2128 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
2129 protected void BroadCastSetFaction(int factionIndex)
2130 {
2131 FactionManager factionManager = GetGame().GetFactionManager();
2132 if (!factionManager)
2133 return;
2134
2135 Faction faction = factionManager.GetFactionByIndex(factionIndex);
2136 m_faction = faction.GetFactionKey();
2138 Event_OnFactionChanged.Invoke(faction);
2139 }
2140
2141 //------------------------------------------------------------------------------------------------
2147 {
2148 return m_faction;
2149 }
2150
2151 //------------------------------------------------------------------------------------------------
2157 {
2158 // If it's a slave group, get faction from master group
2159 if (GetMaster() != null)
2160 return m_MasterGroup.GetFaction();
2161
2162 // Master group:
2163 ArmaReforgerScripted game = GetGame();
2164 if (!game) return null;
2165
2166 FactionManager factionManager = game.GetFactionManager();
2167 if (!factionManager) return null;
2168
2169 return factionManager.GetFactionByKey(m_faction);
2170 }
2171
2177 {
2178 FactionManager factionManager = GetGame().GetFactionManager();
2179 if (!factionManager)
2180 return -1;
2181
2182 return factionManager.GetFactionIndex(GetFaction());
2183 }
2184
2185 //------------------------------------------------------------------------------------------------
2192 static void IgnoreSnapToTerrain(bool ignore)
2193 {
2194 s_bIgnoreSnapToTerrain = ignore;
2195 }
2196
2202 static void IgnoreSpawning(bool ignore)
2203 {
2204 s_bIgnoreSpawning = ignore;
2205 }
2206
2207 //------------------------------------------------------------------------------------------------
2215 {
2216 if (!Event_OnInit)
2218
2219 return Event_OnInit;
2220 }
2221
2229 {
2230 if (!Event_OnEmpty)
2231 Event_OnEmpty = new ScriptInvokerBase<ScriptInvoker_AIGroupOnEmpty_Callback>();
2232
2233 return Event_OnEmpty;
2234 }
2235
2236 //------------------------------------------------------------------------------------------------
2250
2251 //------------------------------------------------------------------------------------------------
2265
2266 //------------------------------------------------------------------------------------------------
2280
2281 //------------------------------------------------------------------------------------------------
2295
2296 //------------------------------------------------------------------------------------------------
2310
2311 //------------------------------------------------------------------------------------------------
2325
2326 //------------------------------------------------------------------------------------------------
2340
2341 //------------------------------------------------------------------------------------------------
2355
2356 //------------------------------------------------------------------------------------------------
2368
2369 //------------------------------------------------------------------------------------------------
2370 ScriptInvokerBase<ScriptInvokerAIGroup> GetOnAllDelayedEntitySpawned()
2371 {
2373 Event_OnAllDelayedEntitySpawned = new ScriptInvokerBase<ScriptInvokerAIGroup>();
2374
2376 }
2377
2378 //------------------------------------------------------------------------------------------------
2379 override void OnEmpty()
2380 {
2381 if (Event_OnEmpty)
2382 Event_OnEmpty.Invoke(this);
2383
2384 //--- Delete after delay, doing it directly in this event would be unsafe
2386 GetGame().GetCallqueue().CallLater(SCR_EntityHelper.DeleteEntityAndChildren, 1, false, this);
2387 }
2388
2389 //------------------------------------------------------------------------------------------------
2390 override void OnAgentAdded(AIAgent child)
2391 {
2393 Event_OnAgentAdded.Invoke(child);
2394
2395 SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(child);
2396 if (agent)
2397 {
2399 }
2400 }
2401
2402 //------------------------------------------------------------------------------------------------
2403 override void OnAgentRemoved(AIAgent child)
2404 {
2406 Event_OnAgentRemoved.Invoke(this, child);
2407 }
2408
2409 //------------------------------------------------------------------------------------------------
2410 override void OnLeaderChanged(AIAgent currentLeader, AIAgent prevLeader)
2411 {
2413 Event_OnLeaderChanged.Invoke(currentLeader, prevLeader);
2414
2415 if (currentLeader)
2416 {
2417 ChimeraCharacter character = ChimeraCharacter.Cast(currentLeader.GetControlledEntity());
2418 if (character)
2419 {
2420 SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(character.GetCharacterController());
2421 if (controller)
2423 }
2424 }
2425
2426 if (!prevLeader)
2427 return;
2428
2429 ChimeraCharacter character = ChimeraCharacter.Cast(prevLeader.GetControlledEntity());
2430 if (character)
2431 {
2432 SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(character.GetCharacterController());
2433 if (controller)
2435 }
2436 }
2437
2438 //------------------------------------------------------------------------------------------------
2439 override void OnCurrentWaypointChanged(AIWaypoint currentWP, AIWaypoint prevWP)
2440 {
2442
2444 Event_OnCurrentWaypointChanged.Invoke(currentWP, prevWP);
2445 }
2446
2447 //------------------------------------------------------------------------------------------------
2448 override void OnWaypointCompleted(AIWaypoint wp)
2449 {
2451
2453 Event_OnWaypointCompleted.Invoke(wp);
2454 }
2455
2456 //------------------------------------------------------------------------------------------------
2457 override void OnWaypointAdded(AIWaypoint wp)
2458 {
2460 Event_OnWaypointAdded.Invoke(wp);
2461 }
2462
2463 //------------------------------------------------------------------------------------------------
2464 override void OnWaypointRemoved(AIWaypoint wp, bool isCurrentWaypoint)
2465 {
2467
2469 Event_OnWaypointToRemove.Invoke(wp, isCurrentWaypoint); // listeners should not delete the waypoint
2470
2472 Event_OnWaypointRemoved.Invoke(wp); // listeners can delete the waypoint
2473 }
2474
2475 //------------------------------------------------------------------------------------------------
2478 protected void InvokeSubagentsOnWaypointChanged(AIWaypoint newWaypoint)
2479 {
2480 array<AIAgent> agents = {};
2481 GetAgents(agents);
2482 foreach (AIAgent agent : agents)
2483 {
2484 SCR_ChimeraAIAgent _agent = SCR_ChimeraAIAgent.Cast(agent);
2485 if (_agent)
2486 _agent.OnGroupWaypointChanged(newWaypoint);
2487 }
2488 }
2489
2490 //------------------------------------------------------------------------------------------------
2491#ifdef WORKBENCH
2492 override bool _WB_OnKeyChanged(BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
2493 {
2494 if (key == "coords")
2495 {
2498 }
2499 return false;
2500 }
2501#endif
2502
2503 //------------------------------------------------------------------------------------------------
2504 override void EOnInit(IEntity owner)
2505 {
2506 m_aAllocatedCompartments = new array<BaseCompartmentSlot>;
2508
2510
2512 {
2513 s_bIgnoreSpawning = false;
2514
2515 //--- Instantly mark as initialized if no team members are to be spawned
2516 if (Event_OnInit)
2517 Event_OnInit.Invoke(this);
2518
2519 return;
2520 }
2521
2522 if (m_bSpawnImmediately || GetWorld().IsEditMode())
2523 SpawnUnits();
2524 }
2525
2526 //------------------------------------------------------------------------------------------------
2527 protected void OnSpawnPointFinalizeSpawn(SCR_SpawnRequestComponent requestComponent, SCR_SpawnData data, IEntity entity)
2528 {
2529 if (requestComponent.GetPlayerId() != m_iLeaderID)
2530 return;
2531
2533 if (!spawnData)
2534 return;
2535
2536 SCR_SpawnPoint spawnPoint = spawnData.GetSpawnPoint();
2537 if (!spawnPoint)
2538 return;
2539
2540 IEntity baseEntity = spawnPoint.GetParent();
2541 if (!baseEntity)
2542 return;
2543
2544 SCR_MilitaryBaseComponent baseComponent = SCR_MilitaryBaseComponent.Cast(baseEntity.FindComponent(SCR_MilitaryBaseComponent));
2545 if (!baseComponent)
2546 return;
2547
2548 SetRallyPoint(baseComponent);
2549 }
2550
2551 //------------------------------------------------------------------------------------------------
2553 {
2554 return m_bSpawnImmediately;
2555 }
2556
2557 //------------------------------------------------------------------------------------------------
2558 void SetSpawnImmediately(bool spawnImmediately)
2559 {
2560 m_bSpawnImmediately = spawnImmediately;
2561 }
2562
2563 //------------------------------------------------------------------------------------------------
2565 {
2566 m_iMaxUnitsToSpawn = cnt;
2567 }
2568
2569 //------------------------------------------------------------------------------------------------
2575 void SetMemberSpawnDelay(int memberSpawnDelay)
2576 {
2577 m_fMemberSpawnDelay = memberSpawnDelay;
2578 }
2579
2580 //------------------------------------------------------------------------------------------------
2582 {
2583 if (SCR_Global.IsEditMode(this))
2584 {
2585 CreateUnitEntities(true, m_aUnitPrefabSlots);
2586 AddVehiclesStatic(m_aStaticVehicles);
2587 AddWaypointsStatic(m_aStaticWaypoints);
2588 AddWaypointsDynamic(m_aSceneWaypointInstances, m_aSpawnedWaypoints);
2589 }
2590 else
2591 {
2592 //--- Don't hardcode members array - it may change in run-time, and we don't want to delete members who meanwhile joined other group
2593 CreateUnitEntities(false, m_aUnitPrefabSlots);
2594 AddVehiclesStatic(m_aStaticVehicles);
2595 AddWaypointsStatic(m_aStaticWaypoints);
2596 AddWaypointsDynamic(null, m_aSpawnedWaypoints);
2597 }
2598 }
2599
2600 //------------------------------------------------------------------------------------------------
2605 {
2606 if (!m_SlaveGroup && (!m_SlaveGroupID || !m_SlaveGroupID.IsValid()))
2607 return null;
2608
2609 if (!m_SlaveGroup && m_SlaveGroupID.IsValid()) // case reference on SlaveGroup has not streamed in, yet
2611
2612 return m_SlaveGroup;
2613 }
2614
2615 //------------------------------------------------------------------------------------------------
2620 {
2621 m_SlaveGroup = group;
2622 group.SetMaster(this);
2623 }
2624
2625 //------------------------------------------------------------------------------------------------
2630 {
2631 if (!m_MasterGroup && (!m_MasterGroupID || !m_MasterGroupID.IsValid()))
2632 return null;
2633
2634 if (!m_MasterGroup && m_MasterGroupID.IsValid()) // case reference on MasterGroup has not streamed in, yet
2636
2637 return m_MasterGroup;
2638 }
2639
2640 //------------------------------------------------------------------------------------------------
2645 {
2646 m_MasterGroup = group;
2647 }
2648
2649 //------------------------------------------------------------------------------------------------
2650 array<SCR_ChimeraCharacter> GetAIMembers()
2651 {
2652 return m_aAIMembers;
2653 }
2654
2655 //------------------------------------------------------------------------------------------------
2656 /*
2657 returns true if SCR_ChimeraCharacter is a member of slave subgroup that is linked to this playable SCR_AIGroup
2658 */
2659 bool IsAIControlledCharacterMember(SCR_ChimeraCharacter character)
2660 {
2661 if (!character)
2662 return false;
2663 //if group doesnt have slave group for AIs, AI is automatically not a member
2664 if (GetSlave() == null)
2665 return false;
2666 return m_SlaveGroup.m_aAIMembers.Find(character) != -1;
2667 }
2668
2669 //------------------------------------------------------------------------------------------------
2671 {
2672 SCR_Faction scrFaction = SCR_Faction.Cast(GetFaction());
2673 if (!scrFaction)
2674 return false;
2675
2676 array<SCR_GroupRolePresetConfig> groupRolePresets = {};
2677 scrFaction.GetGroupRolePresetConfigs(groupRolePresets);
2678
2679 // find loadout in faction predefined groups
2680 foreach (SCR_GroupRolePresetConfig groupRolePreset : groupRolePresets)
2681 {
2682 if (groupRolePreset && groupRolePreset.GetGroupRole() == m_eGroupRole)
2683 return groupRolePreset.IsLoadoutInGroup(loadout);
2684 }
2685
2686 return false;
2687 }
2688
2689 //------------------------------------------------------------------------------------------------
2690 override bool RplSave(ScriptBitWriter writer)
2691 {
2692 if (!m_UiInfo)
2694
2695 int factionIndex = -1;
2696 FactionManager factionManager = GetGame().GetFactionManager();
2697 if (factionManager)
2698 factionIndex = factionManager.GetFactionIndex(GetFaction());
2699
2700 writer.WriteInt(factionIndex);
2701 writer.WriteInt(m_iGroupRadioFrequency);
2702 writer.WriteInt(m_iGroupID);
2703
2704 int count = m_aPlayerIDs.Count();
2705 writer.WriteInt(count);
2706 for (int i = count - 1; i >= 0; i--)
2707 {
2708 writer.WriteInt(m_aPlayerIDs[i]);
2709 }
2710 writer.WriteInt(m_iLeaderID);
2711 writer.WriteBool(m_bPrivate);
2712
2713 writer.WriteInt(m_iDescriptionAuthorID);
2714 writer.WriteInt(m_iNameAuthorID);
2715
2716 writer.WriteString(m_sCustomDescription);
2717 writer.WriteString(m_sCustomName);
2718
2719 writer.WriteString(m_UiInfo.GetGroupFlag());
2720 writer.WriteBool(m_UiInfo.GetFlagIsFromImageSet());
2721
2723 writer.WriteRplId(m_MasterGroupID);
2725 writer.WriteRplId(m_SlaveGroupID);
2726
2727 writer.WriteInt(m_iMaxMembers);
2728
2729 writer.WriteInt(m_eRequiredRank);
2730
2731 writer.WriteInt(m_eGroupRole);
2732 writer.WriteBool(m_bIsPrivacyChangeable);
2733 writer.WriteBool(m_bIsCreatedByCommander);
2734
2735 writer.WriteInt(m_RallyPointId);
2736 writer.WriteBool(m_bForcedRallyPoint);
2737
2738 //do rpcs for players join/leave
2739 //add invokers for players join/leave
2740
2741 return true;
2742 }
2743
2744 //------------------------------------------------------------------------------------------------
2745 override bool RplLoad(ScriptBitReader reader)
2746 {
2747 int factionIndex;
2748 reader.ReadInt(factionIndex);
2749 if (factionIndex >= 0)
2750 BroadCastSetFaction(factionIndex);
2751
2752 reader.ReadInt(m_iGroupRadioFrequency);
2753 reader.ReadInt(m_iGroupID);
2754
2755 int count, playerID;
2756 reader.ReadInt(count);
2757 for (int i = count - 1; i >= 0; i--)
2758 {
2759 reader.ReadInt(playerID);
2760 m_aPlayerIDs.Insert(playerID);
2761 }
2762
2763 if (m_bPlayable)
2764 {
2765 SCR_GroupsManagerComponent groupsManager = SCR_GroupsManagerComponent.GetInstance();
2766 if (groupsManager)
2767 {
2768 groupsManager.RegisterGroup(this);
2769 groupsManager.ClaimFrequency(GetRadioFrequency(), GetFaction());
2770 groupsManager.OnGroupCreated(this);
2771 }
2772 }
2773
2774 int temp;
2775 reader.ReadInt(temp);
2776 RPC_SetLeaderID(temp);
2777
2778 reader.ReadBool(m_bPrivate);
2779
2780 reader.ReadInt(m_iDescriptionAuthorID);
2781 reader.ReadInt(m_iNameAuthorID);
2782
2783 string customDesc, customName;
2784 reader.ReadString(customDesc);
2785 reader.ReadString(customName);
2786
2789
2790 if (!m_UiInfo)
2792
2793 string flag;
2794 reader.ReadString(flag);
2795 m_UiInfo.SetGroupFlag(flag);
2796
2797 bool isFromImageSet;
2798 reader.ReadBool(isFromImageSet);
2799 m_UiInfo.SetFlagIsFromImageSet(isFromImageSet);
2800
2801 reader.ReadRplId(m_MasterGroupID);
2803 reader.ReadRplId(m_SlaveGroupID);
2805
2806 reader.ReadInt(m_iMaxMembers);
2807
2808 reader.ReadInt(m_eRequiredRank);
2809
2810 reader.ReadInt(m_eGroupRole);
2811 reader.ReadBool(m_bIsPrivacyChangeable);
2812 reader.ReadBool(m_bIsCreatedByCommander);
2813
2814 reader.ReadInt(m_RallyPointId);
2815 reader.ReadBool(m_bForcedRallyPoint);
2816
2817 return true;
2818 }
2819
2820 //------------------------------------------------------------------------------------------------
2822 {
2823 if (newLifeState == ECharacterLifeState.INCAPACITATED)
2825 }
2826
2827 //------------------------------------------------------------------------------------------------
2829 {
2830 array<AIAgent> groupAgents = {};
2831 GetAgents(groupAgents);
2832
2833 for (int i = 1; i < groupAgents.Count(); i++)
2834 {
2835 ChimeraCharacter character = ChimeraCharacter.Cast(groupAgents.Get(i).GetControlledEntity());
2836 if (!character)
2837 continue;
2838
2839 CharacterControllerComponent charController = character.GetCharacterController();
2840 if (!charController)
2841 continue;
2842
2843 if (!charController.IsUnconscious())
2844 {
2845 SetNewLeader(groupAgents.Get(i));
2846 return;
2847 }
2848 }
2849 }
2850
2851 //------------------------------------------------------------------------------------------------
2853 {
2855 Replication.BumpMe();
2856 }
2857
2858 //------------------------------------------------------------------------------------------------
2860 {
2861 if (m_iDeployedRadioCount < 1)
2862 return;
2863
2865 Replication.BumpMe();
2866 }
2867
2868 //------------------------------------------------------------------------------------------------
2870 {
2871 return m_iDeployedRadioCount;
2872 }
2873
2874 //------------------------------------------------------------------------------------------------
2875 void SetDeleteWhenEmpty(bool deleteWhenEmpty)
2876 {
2877 m_bDeleteWhenEmpty = deleteWhenEmpty;
2878 }
2879
2880 //------------------------------------------------------------------------------------------------
2882 {
2883 array<AIWaypoint> aiWaypoints = {};
2884 GetWaypoints(aiWaypoints);
2885
2886 foreach (AIWaypoint aiWaypoint : aiWaypoints)
2887 {
2888 CompleteWaypoint(aiWaypoint);
2889 }
2890 }
2891
2892 //------------------------------------------------------------------------------------------------
2894 {
2895 SetEventMask(EntityEvent.INIT);
2896 }
2897
2898 //------------------------------------------------------------------------------------------------
2900 {
2901 // Group is playable so we have to unregister it locally as well
2902 if (m_bPlayable)
2903 {
2904 SCR_GroupsManagerComponent groupsManager = SCR_GroupsManagerComponent.GetInstance();
2905 if (groupsManager)
2906 {
2907 groupsManager.UnregisterGroup(this);
2908 groupsManager.GetOnPlayableGroupRemoved().Invoke(this);
2909 }
2910 }
2911
2913
2916 RemoveStaticWaypointRefs(m_aStaticWaypoints);
2917 }
2918}
2919
2920//------------------------------------------------------------------------------------------------
2921enum EGroupState
2922{
2923 IDLE = 0,
2933}
2934
2935//------------------------------------------------------------------------------------------------
2937enum SCR_EAIGroupFormation
2938{
2942 StaggeredColumn
2943}
2944
2945//------------------------------------------------------------------------------------------------
2946[BaseContainerProps(namingConvention: NamingConvention.NC_MUST_HAVE_NAME)]
2947class SCR_WaypointPrefabLocation
2949 [Attribute("{750A8D1695BD6998}AI/Entities/Waypoints/AIWaypoint.et", UIWidgets.ResourceAssignArray, "Prefab for the waypoint")]
2950 ResourceName m_WPPrefabName;
2952 [Attribute("", UIWidgets.EditBox, "Waypoint name")]
2953 string m_WPInstanceName;
2954
2955 [Attribute("", UIWidgets.EditBox, "Waypoint location")]
2956 vector m_WPWorldLocation;
2957
2958 [Attribute("0", UIWidgets.EditBox, "Waypoint completion radius (-1 dont override default)")]
2959 float m_WPRadiusOverride;
2960
2961 [Attribute("0", UIWidgets.EditBox, "Waypoint completion time (-1 dont override default)")]
2962 float m_WPTimeOverride;
2963}
2964
2965//---- REFACTOR NOTE END ----
AddonBuildInfoTool id
ref DSGameConfig game
Definition DSConfig.c:81
ENotification
EWaterSurfaceType
ArmaReforgerScripted GetGame()
Definition game.c:1398
PlatformKind
Definition PlatformKind.c:8
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
SCR_AIGroup Wedge
Names of enum values must match formation names in AIWorld.
func ScriptInvokerAIGroup
Definition SCR_AIGroup.c:4
SCR_AIGroup REQ_SUPPORT
func ScriptInvoker_AIGroupOnEmpty_Callback
Definition SCR_AIGroup.c:71
bool editMode
Definition SCR_AIGroup.c:67
ResourceName resourceName
Definition SCR_AIGroup.c:66
ScriptInvokerBase< ScriptInvoker_AIGroupOnEmpty_Callback > ScriptInvoker_AIGroupOnEmpty
Definition SCR_AIGroup.c:72
ref array< ResourceName > m_aUnitPrefabSlots
ref array< IEntity > m_aSceneGroupUnitInstances
SCR_AIGroup Column
int index
Definition SCR_AIGroup.c:65
SCR_AIGroupClass snapToTerrain
SCR_AIGroup Line
SCR_AIGroup MANEUVERING
func ScriptInvokerGroupRoleMethod
Definition SCR_AIGroup.c:7
ScriptInvokerBase< ScriptInvokerGroupRoleMethod > ScriptInvokerGroupRole
Definition SCR_AIGroup.c:8
SCR_AIGroup REQ_ORDERS
SCR_AIGroup RETREATING
SCR_AIGroup MOVING
SCR_AIGroupInfoComponentClass IDLE
Group has no waypoints and does not engage an enemy.
@ FOLLOW
SCR_BaseGameMode GetGameMode()
SCR_CacheNoteComponentClass ScriptComponentClass RplProp()] protected ref array< string > m_aLines
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
override bool _WB_OnKeyChanged(IEntity owner, BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
Any property value has been changed. You can use editor API here and do some additional edit actions ...
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
SCR_EGroupRole
Group roles.
Get all prefabs that have the spawner data
int GetPlayerCount()
void SCR_GroupsManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void SetCompartmentAccessible(bool val)
proto external Managed FindComponent(typename typeName)
proto external BaseWorld GetWorld()
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
Replication item identifier.
Definition RplId.c:14
void AddDeniedRequester(int playerID)
void SetNewConsciousLeader()
array< SCR_ChimeraCharacter > GetAIMembers()
override bool RplSave(ScriptBitWriter writer)
SCR_AIGroup m_SlaveGroup
void RemovePlayer(int playerID)
Called on the server (authority).
ref array< SCR_ChimeraCharacter > m_aAIMembers
void SpawnUnits()
bool IsLoadoutInGroup(SCR_FactionPlayerLoadout loadout)
int GetPlayerCount(bool checkMasterAndSlaves=false)
string GetCustomNameWithOriginal()
string GetGroupRoleName()
void QueueAddAgent(int playerID)
RplId m_MasterGroupID
int m_iDefaultActiveRadioChannel
static ScriptInvoker GetOnPrivateGroupChanged()
static ScriptInvokerGroupRole GetOnGroupRoleChanged()
bool IsPlayerLeader(int playerID)
void RemovePlayerAgent(int playerID)
void SetGroupID(int id)
void SpawnAllImmediately()
int m_iDescriptionAuthorID
SCR_AIGroup GetSlave()
void ~SCR_AIGroup()
static ScriptInvoker GetOnPlayerRemoved()
ScriptInvoker GetOnLeaderChanged()
static ref ScriptInvoker s_OnFrequencyChanged
int m_iGroupRadioFrequency
void DestroyEntities(out array< IEntity > entityList)
void OnMemberDeath(notnull SCR_CharacterControllerComponent memberController, IEntity killerEntity, Instigator killer)
ScriptInvoker GetOnAgentRemoved()
void OnSpawnPointFinalizeSpawn(SCR_SpawnRequestComponent requestComponent, SCR_SpawnData data, IEntity entity)
static ref ScriptInvoker s_OnFlagSelected
bool InitFactionKey(string factionKey)
void GetCallsigns(out string company, out string platoon, out string squad, out string character, out string format)
void RemoveRequester(int playerID)
void RemoveWaypointFromGroup(AIWaypoint waypoint)
void AllocateSmartActions(array< AISmartActionComponent > components)
RplId m_SlaveGroupID
SCR_EGroupRole GetGroupRole()
bool GetFlagIsFromImageSet()
static ref ScriptInvoker s_OnJoinPrivateGroupConfirm
void SetCustomDescription(string desc, int authorID)
called on server only
void AddPlayer(int playerID)
Called on the server (authority).
void ListenToMemberDeath(notnull IEntity groupMember)
void SetWaypointParams(out AIWaypoint wp, SCR_WaypointPrefabLocation prefabParams)
void SetCustomName(string name, int authorID)
void OnControllableEntitySpawned(IEntity controlledEntity, notnull SCR_GadgetManagerComponent gadgetManager)
static bool s_bIgnoreSnapToTerrain
void AddWaypointsStatic(array< string > aWaypointNames)
SCR_ECharacterRank GetRequiredRank()
void CreateUnitEntities(bool editMode, array< ResourceName > entityResourceNames)
array< int > GetPlayerIDs()
void BroadCastSetFaction(int factionIndex)
SCR_AIGroup m_MasterGroup
ResourceName GetPresetResource()
static ref ScriptInvokerBase< ScriptInvokerAIGroup > s_OnGroupRallyPointChanged
int GetFirstPlayerLeaderID()
void OnGroupMemberStateChange()
Should only be called on the server (authority).
void RpcDo_SetGroupRole(SCR_EGroupRole groupRole)
bool SpawnGroupMember(bool snapToTerrain, int index, ResourceName res, bool editMode, bool isLast)
void RPC_DoSetCustomDescription(string desc, int authorID)
void SetCreatedByCommander(bool isCreatedByCommander)
bool HasRequesterID(int id)
static ref ScriptInvoker s_OnJoinPrivateGroupCancel
void SetPresetResource(ResourceName preset)
void AddWaypointToGroup(AIWaypoint waypoint)
ref ScriptInvoker Event_OnAgentRemoved
void ReleaseCompartment(BaseCompartmentSlot compartment)
void AddAgentFromControlledEntity(notnull IEntity controlledEntity)
string GetCustomName()
ref array< int > m_aDeniedRequesters
void RPC_SetPrivate(bool isPrivate)
static ref ScriptInvoker s_OnPlayerAdded
void SetMemberSpawnDelay(int memberSpawnDelay)
void SetFlagIsFromImageSet(bool value)
ref SCR_ScriptProfanityFilterRequestCallback m_ProfanityCallbackDesc
void SetSpawnImmediately(bool spawnImmediately)
override void OnCurrentWaypointChanged(AIWaypoint currentWP, AIWaypoint prevWP)
static ScriptInvoker GetOnCustomNameChanged()
void ReleaseCompartments()
ScriptInvoker GetOnWaypointCompleted()
void SetRadioFrequency(int frequency)
SCR_ECharacterRank m_eRequiredRank
void BeginDelayedSpawn()
ref ScriptInvoker Event_OnLeaderChanged
int GetRallyPointId()
int GetDescriptionAuthorID()
void RpcDo_SetRequiredRank(SCR_ECharacterRank rank)
bool IsPrivacyChangeable()
override void OnWaypointAdded(AIWaypoint wp)
bool IsRallyPointForced()
void ClearRequesters()
void SetRequiredRank(SCR_ECharacterRank rank)
ResourceName m_rPreset
ref ScriptInvoker Event_OnWaypointRemoved
int m_iMaxUnitsToSpawn
int GetRequesterIDs(out array< int > valueArray)
ScriptInvoker GetOnWaypointRemoved()
override void OnAgentRemoved(AIAgent child)
ScriptInvoker GetOnMemberStateChange()
void SetPrivate(bool isPrivate)
Called on the server (authority).
void RemoveStaticWaypointRefs(array< string > aWaypointNames)
bool m_bDeleteWhenEmpty
ref array< AISmartActionComponent > m_aAllocatedComponents
int GetNumberOfMembersToSpawn()
int GetFactionIndex()
int GetTotalAgentCount()
override void OnWaypointRemoved(AIWaypoint wp, bool isCurrentWaypoint)
void SetPrivacyChangeable(bool IsPrivacyChangeable)
void OnPlayerLeftGame(int playerId)
bool IsInitializing()
Returns true if group is in initialization state, for instance while still spawning its members.
ref array< int > m_aAgentIDQueue
static ref ScriptInvoker< SCR_AIGroup > s_OnCustomNameChanged
int GetAgentCountIncludingMasterAndSlaves()
ref array< int > m_aRequesterIDs
void SetSlave(SCR_AIGroup group)
ref ScriptInvoker Event_OnWaypointCompleted
void SetRallyPoint(notnull SCR_MilitaryBaseComponent base, bool force=false)
void AllocateCompartment(BaseCompartmentSlot compartment)
void SetGroupFlag(int flagIndex, bool isFromImageset)
called on server only
void SetMaxGroupMembers(int value)
void SetMaxMembers(int maxMembers)
called on server only
void RPC_DoSetMaxMembers(int maxMembers)
ScriptInvokerBase< ScriptInvokerAIGroup > GetOnAllDelayedEntitySpawned()
int GetRadioFrequency()
void SetCanDeleteIfNoPlayer(bool deleteEmpty)
Sets if the group should be deleted when all players leave.
void SetMaster(SCR_AIGroup group)
int GetMaxMembers()
ScriptInvoker GetOnWaypointToRemove()
void OnNameFilteredCallback(array< string > resultText)
ScriptInvoker GetOnWaypointAdded()
int m_iDeployedRadioCount
int GetPlayerAndAgentCount(bool checkMasterAndSlaves=false)
bool RemoveAIEntityFromGroup(IEntity entity)
static void IgnoreSpawning(bool ignore)
static ScriptInvoker GetOnPlayerLeaderChanged()
static bool s_bIgnoreSpawning
static ScriptInvoker GetOnJoinPrivateGroupRequest()
void EndDelayedSpawn()
static ScriptInvoker GetOnPlayerAdded()
void CompleteAllWaypoints()
void RPC_DoClearDeniedRequester()
bool GetSpawnImmediately()
override bool RplLoad(ScriptBitReader reader)
static ScriptInvoker GetOnJoinPrivateGroupConfirm()
override void EOnFrame(IEntity owner, float timeSlice)
override void EOnInit(IEntity owner)
void RemoveAgentFromControlledEntity(notnull IEntity controlledEntity)
SCR_AIGroupUtilityComponent GetGroupUtilityComponent()
bool IsPrivate()
ref ScriptInvoker Event_OnFactionChanged
SCR_AIGroup GetMaster()
ref SCR_AIGroupUIInfo m_UiInfo
int GetSpawnQueueSize()
override void OnWaypointCompleted(AIWaypoint wp)
ref array< IEntity > m_aSceneGroupUnitInstances
void AddRequester(int playerID)
ref ScriptInvoker Event_OnInit
ref ScriptInvoker_AIGroupOnEmpty Event_OnEmpty
void ClearDeniedRequester()
ScriptInvoker GetOnAgentAdded()
int GetNameAuthorID()
void RPC_DoAddDeniedRequester(int playerID)
void AddVehiclesStatic(array< string > aVehicleNames)
void RpcDo_RemoveRallyPoint()
int GetGroupID()
bool SetFaction(Faction faction)
static ref ScriptInvoker< int, int > s_OnPlayerLeaderChanged
void ReleaseSmartAction(AISmartActionComponent component)
bool IsFull()
void RPC_DoRemoveRequester(int playerID)
ref array< BaseCompartmentSlot > m_aAllocatedCompartments
bool IsSlave()
void RPC_SetLeaderID(int playerID)
static ref ScriptInvoker s_OnCustomDescChanged
ref array< IEntity > m_aSceneWaypointInstances
static void IgnoreSnapToTerrain(bool ignore)
ref ScriptInvokerBase< ScriptInvokerAIGroup > Event_OnAllDelayedEntitySpawned
static ref ScriptInvoker s_OnPrivateGroupChanged
static ref ScriptInvoker s_OnPlayerRemoved
void OnPlayerDisconnected(int playerID)
Should be only called on the server.
void AddOnGadgetsLoadedListener(int playerID, notnull IEntity controlledEntity)
override void OnEmpty()
int m_iNameAuthorID
ref SCR_ScriptProfanityFilterRequestCallback m_ProfanityCallbackName
bool m_bIsCreatedByCommander
void RPC_DoSetGroupFlag(int flagIndex, bool isFromImageset)
int GetDeniedRequesters(out array< int > valueArray)
string GetCustomDescription()
ref ScriptInvoker Event_OnGroupMemberStateChange
ScriptInvoker GetOnCurrentWaypointChanged()
static ScriptInvoker GetOnFlagSelected()
ScriptInvoker_AIGroupOnEmpty GetOnEmpty()
void RPC_DoAddPlayer(int playerID)
void RPC_DoSetPrivacyChangeable(bool IsPrivacyChangeable)
ref ScriptInvoker Event_OnWaypointToRemove
bool SpawnDelayedGroupMember(int spawnIndex)
bool m_bIsPrivacyChangeable
void AddWaypointsDynamic(out array< IEntity > entityInstanceList, array< ref SCR_WaypointPrefabLocation > prefabs)
void SetNumberOfMembersToSpawn(int number)
void NotificateGroupAIChange(IEntity controlledEntity, ENotification notificationType)
void CheckForLeader(int playerID, bool noLeaderAllowed)
void InvokeSubagentsOnWaypointChanged(AIWaypoint newWaypoint)
bool IsCreatedByCommander()
void SetCustomGroupFlag(ResourceName flag)
void SetFactionDelayed(int factionIndex)
override void OnAgentAdded(AIAgent child)
void RPC_DoSetMaxGroupMembers(int value)
ref ScriptInvoker Event_OnAgentAdded
void SetGroupRole(SCR_EGroupRole groupRole)
void RemoveRallyPoint()
Removes current group Rally Point.
static ScriptInvoker GetOnFrequencyChanged()
static ScriptInvoker GetOnCustomDescriptionChanged()
void RPC_DoRemoveLeavingPlayer(int playerID)
static ref ScriptInvoker s_OnMaxMembersChanged
void ReleaseSmartActions()
int GetLeaderID()
static ref ScriptInvokerGroupRole s_OnGroupRoleChanged
override void OnLeaderChanged(AIAgent currentLeader, AIAgent prevLeader)
ScriptInvoker GetOnInit()
void RPC_DoRemovePlayer(int playerID)
bool m_bForcedRallyPoint
static ScriptInvokerBase< ScriptInvokerAIGroup > GetOnGroupRallyPointChanged()
bool AddAIEntityToGroup(IEntity entity)
void RPC_DoAddRequester(int playerID)
bool IsAIControlledCharacterMember(SCR_ChimeraCharacter character)
void IncreaseDeployedRadioCount()
ref ScriptInvoker Event_OnCurrentWaypointChanged
Faction GetFaction()
bool GetDeleteIfNoPlayer()
Returns true if the group is set to be deleted when all players leave.
void RPC_DoOnGroupMemberStateChange()
ScriptInvoker GetOnFactionChanged()
bool IsMaxMembersLimited()
void SCR_AIGroup(IEntitySource src, IEntity parent)
ref ScriptInvoker Event_OnWaypointAdded
void SetDefaultActiveRadioChannel(int id)
static bool DeLocalizeText(out string input)
void RPC_DoSetFrequency(int frequency)
void GetAllocatedSmartActions(out array< AISmartActionComponent > allocatedComponents)
bool IsPlayerInGroup(int playerID)
string m_sCustomName
ref array< ref SCR_AIGroup_DelayedSpawn > m_delayedSpawnList
bool IsPlayable()
int GetDeployedRadioCount()
string GetFactionName()
void RPC_DoSetCustomName(string name, int authorID)
void RPC_DoClearRequesterIDs()
int m_fMemberSpawnDelay
Definition SCR_AIGroup.c:98
void GetAllocatedCompartments(out array< BaseCompartmentSlot > allocatedCompartments)
SCR_AIGroupUtilityComponent m_GroupUtilityComponent
string m_sCustomDescription
int m_iNumOfMembersToSpawn
void RpcDo_SetRallyPoint(int callsignId, bool force)
void SetGroupLeader(int playerID)
Called on the server (authority).
void ClearRefs(out array< IEntity > entityList)
ref array< int > m_aPlayerIDs
void LeaderLifeStateChanged(ECharacterLifeState previousLifeState, ECharacterLifeState newLifeState)
ResourceName GetGroupFlag()
void RpcDo_SetCreatedByCommander(bool isCreatedByCommander)
void SetMaxUnitsToSpawn(int cnt)
int GetTotalPlayerCount()
void DecreaseDeployedRadioCount()
static ref ScriptInvoker s_OnJoinPrivateGroupRequest
SCR_EGroupRole m_eGroupRole
bool m_bDeleteIfNoPlayer
void SetDeleteWhenEmpty(bool deleteWhenEmpty)
int GetDefaultActiveRadioChannel()
static ScriptInvoker GetOnJoinPrivateGroupCancel()
void OnDescFilteredCallback(array< string > resultText)
static SCR_AIVehicleUsageComponent FindOnNearestParent(notnull IEntity ent, out IEntity componentOwner)
ScriptInvokerBase< SCR_BaseGameMode_OnPlayerDisconnected > GetOnPlayerDisconnected()
ScriptInvokerBase< SCR_BaseGameMode_PlayerIdAndEntity > GetOnPlayerSpawned()
OnPlayerDeathWithParamInvoker GetOnPlayerDeathWithParam()
ref OnLifeStateChangedInvoker m_OnLifeStateChanged
void OnGroupWaypointChanged(AIWaypoint newWaypoint)
ResourceName GetFlagName(int index)
void GetGroupRolePresetConfigs(notnull array< SCR_GroupRolePresetConfig > groupArray)
int GetGroupFlagTextures(out array< ResourceName > textures)
static ScriptInvoker GetOnGadgetInitDoneInvoker()
static bool IsEditMode()
Definition Functions.c:1566
Handles filtering profanities in texts.
Spawn point entity defines positions on which players can possibly spawn.
static SCR_SpawnPointFinalizeSpawn_Invoker GetOnSpawnPointFinalizeSpawn()
void EntitySpawnParams()
Definition gameLib.c:130
proto external void SetNewLeader(AIAgent newLeader)
proto external void ActivateAI()
Activates AI group, removes unwanted prefabs, balances units count, sets on agent remove and add even...
proto external AIWaypoint GetCurrentWaypoint()
proto external int GetWaypoints(out array< AIWaypoint > outWaypoints)
proto external bool CanLimitedAIBeAdded()
proto external void DeactivateAI()
proto external void CompleteWaypoint(AIWaypoint w)
Completes specified waypoint and removes it from the list of waypoints, no need to call RemoveWaypoin...
proto external int GetAgents(notnull out array< AIAgent > outAgents)
AIGroupClass AIAgentClass AddAgent(AIAgent pAgent)
proto external void RemoveWaypoint(AIWaypoint w)
proto external void AddWaypoint(AIWaypoint w)
proto external void RemoveAgent(AIAgent pAgent)
proto external int GetAgentsCount()
ECharacterLifeState
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
EUserInteraction
Interaction type between two players.
void RplRpc(RplChannel channel, RplRcver rcver, RplCondition condition=RplCondition.None, string customConditionName="")
Definition EnNetwork.c:95
RplRcver
Definition RplRcver.c:59
RplChannel
Communication channel. Reliable is guaranteed to be delivered. Unreliable not.
Definition RplChannel.c:14
proto native vector Vector(float x, float y, float z)
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134