Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIGroupCohesionComponent.c
Go to the documentation of this file.
1[ComponentEditorProps(category: "GameScripted/AI", description: "Component for checking group cohesion and giving awards accordingly")]
5
6class SCR_AIGroupCohesionComponent : ScriptComponent
7{
8 [Attribute("90", desc: "Time at which Group Cohesion will be evaluated in seconds")]
9 protected float m_fGroupCohesionCheck;
10
11 [Attribute("100", desc: "Distance between players at which they are considered part of the same group")]
12 protected float m_fGroupCohesionRadius;
13
14 [Attribute("2", desc: "XP increment per player on the group")]
15 protected float m_fGroupCohesionXpIncreasePerPlayer;
16
17 [Attribute("3", desc: "Amount of times the XP awarded will be increased in every check where the group is together")]
18 protected int m_iMaxGroupCohesionLevel;
19
20 [Attribute("false", desc: "Activate/Deactivate debug draws with information about cohesion level and XP awarded")]
21 protected bool m_bDebugActive;
22
23 protected int m_iGroupCohesionLevel = 0;
24
25 protected SCR_AIGroup m_Group;
26
27 // Debug properties
28 private int m_iLastAwardedXP = 0;
29 private int m_iLastGroupCount = 0;
30
31 //------------------------------------------------------------------------------------------------
32 protected float GetGroupCohesionCheckTimeInMs()
33 {
34 return m_fGroupCohesionCheck * 1000;
35 }
36
37 //------------------------------------------------------------------------------------------------
38 override protected void OnPostInit(IEntity owner)
39 {
40 RplComponent rplComponent = RplComponent.Cast(owner.FindComponent(RplComponent));
41
42 m_Group = SCR_AIGroup.Cast(owner);
43
44 if (!m_Group)
45 return;
46
47 if (!rplComponent || !rplComponent.IsMaster())
48 return;
49
50 m_Group.GetOnPlayerAdded().Insert(OnPlayerAddedToGroup);
51 }
52
53 //------------------------------------------------------------------------------------------------
54 protected void OnPlayerAddedToGroup(SCR_AIGroup aiGroup, int playerID)
55 {
56 if (m_Group != aiGroup || aiGroup.GetPlayerCount() < 2)
57 return;
58
59 GetGame().GetCallqueue().CallLater(CheckGroupCohesion, GetGroupCohesionCheckTimeInMs(), true);
60
61 if (m_bDebugActive)
62 GetGame().GetCallqueue().CallLater(DrawDebug, 0, true);
63
64 aiGroup.GetOnPlayerAdded().Remove(OnPlayerAddedToGroup);
66 }
67
68 //------------------------------------------------------------------------------------------------
69 protected void OnPlayerRemovedFromGroup(SCR_AIGroup aiGroup, int playerID)
70 {
71 if (m_Group != aiGroup || aiGroup.GetPlayerCount() >= 2)
72 return;
73
74 GetGame().GetCallqueue().Remove(CheckGroupCohesion);
75
76 if (m_bDebugActive)
77 GetGame().GetCallqueue().Remove(DrawDebug);
78
79 aiGroup.GetOnPlayerAdded().Insert(OnPlayerAddedToGroup);
81 }
82
83 //------------------------------------------------------------------------------------------------
84 protected void DrawDebug()
85 {
86 DbgUI.Begin("Cohesion Debug");
87 DbgUI.Text("Cohesion Time: " + m_iGroupCohesionLevel * m_fGroupCohesionCheck + "s");
88 DbgUI.Text("Last Player Count on Group: " + m_iLastGroupCount + "/" + m_Group.GetPlayerCount());
89 DbgUI.Text("Last awarded XP: " + m_iLastAwardedXP + "xp");
90 DbgUI.End();
91 }
92
93 //------------------------------------------------------------------------------------------------
94 protected void CreateAgentDistanceGraph(out array< ref array<int>> playerGraph, array<int> players, int playerCount)
95 {
96 playerGraph.Reserve(playerCount);
97
98 for (int i = 0; i < playerCount; ++i)
99 {
100 playerGraph.Insert({});
101 }
102
103 float cohesionRadiusSq = m_fGroupCohesionRadius * m_fGroupCohesionRadius;
104
105 for (int player1Index = 0; player1Index < playerCount - 1; ++player1Index)
106 {
107 IEntity player1 = GetGame().GetPlayerManager().GetPlayerControlledEntity(players[player1Index]);
108 if (!player1)
109 continue;
110
111 for (int player2Index = 0; player2Index < playerCount; ++player2Index)
112 {
113 if (player1Index == player2Index)
114 continue;
115
116 IEntity player2 = GetGame().GetPlayerManager().GetPlayerControlledEntity(players[player2Index]);
117 if (!player2)
118 continue;
119
120 bool areInRange = (vector.DistanceSqXZ(player1.GetOrigin(), player2.GetOrigin()) <= cohesionRadiusSq);
121
122 if (!areInRange)
123 continue;
124
125 playerGraph[player1Index].Insert(player2Index);
126 playerGraph[player2Index].Insert(player1Index);
127 }
128 }
129 }
130
131 //------------------------------------------------------------------------------------------------
132 private void FindUnusedAdjacentAgentGraph(int agent, array< ref array<int>> playerGraph, out array<int> group, out array<int> usedAgents)
133 {
134 usedAgents.Insert(agent);
135 group.Insert(agent);
136
137 array<int> currentAgentGraph = playerGraph[agent];
138
139 foreach (int adjacentAgent : currentAgentGraph)
140 {
141 if (usedAgents.Find(adjacentAgent) < 0)
142 FindUnusedAdjacentAgentGraph(adjacentAgent, playerGraph, group, usedAgents);
143 }
144 }
145
146 //------------------------------------------------------------------------------------------------
147 protected void FindGroupFromAgentDistanceGraph(out array<int> biggestGroup, const array< ref array<int>> playerGraph, int playerCount, int groupMinSize)
148 {
149 array<int> usedAgents = {};
150 usedAgents.Reserve(playerCount);
151
152 for (int agentToCheck = 0; agentToCheck < playerCount - 1; ++agentToCheck)
153 {
154 array<int> group = {};
155
156 FindUnusedAdjacentAgentGraph(agentToCheck, playerGraph, group, usedAgents);
157
158 if (group.Count() >= groupMinSize)
159 {
160 biggestGroup = group;
161 return;
162 }
163
164 if (group.Count() > biggestGroup.Count())
165 biggestGroup = group;
166
167 if (biggestGroup.Count() > playerCount - usedAgents.Count())
168 return;
169 }
170 }
171
172 //------------------------------------------------------------------------------------------------
173 protected bool GetGroupOfPlayersInCohesion(out notnull array<int> playerGroup, out notnull array<int> players, out int groupMinSize)
174 {
175 players = m_Group.GetPlayerIDs();
176 int playerCount = players.Count();
177
178 if (playerCount <= 1)
179 return false;
180
181 groupMinSize = (playerCount / 2) + 1;
182
183 array<ref array<int>> playerGraph = {};
184 CreateAgentDistanceGraph(playerGraph, players, playerCount);
185
186 FindGroupFromAgentDistanceGraph(playerGroup, playerGraph, playerCount, groupMinSize);
187
188 return true;
189 }
190
191 //------------------------------------------------------------------------------------------------
192 protected void AwardXPToGroup(array<int> playerGroup, array<int> players, int groupMinSize)
193 {
194 if (playerGroup.Count() >= groupMinSize)
195 {
196 SCR_XPHandlerComponent compXP = SCR_XPHandlerComponent.Cast(GetGame().GetGameMode().FindComponent(SCR_XPHandlerComponent));
197
198 m_iGroupCohesionLevel = Math.ClampInt(m_iGroupCohesionLevel + 1, 0, m_iMaxGroupCohesionLevel);
199
200 int XPToAward = m_fGroupCohesionXpIncreasePerPlayer * (playerGroup.Count()) * m_iGroupCohesionLevel;
201
202 m_iLastAwardedXP = XPToAward;
203
204 foreach (int playerIndex : playerGroup)
205 {
206 compXP.AwardXP(players[playerIndex], SCR_EXPRewards.GROUP_COHESION, 1.0, false, XPToAward);
207 }
208 }
209 else
210 {
211 m_iGroupCohesionLevel = 0;
212 m_iLastAwardedXP = 0;
213 }
214 }
215
216 //------------------------------------------------------------------------------------------------
217 protected void CheckGroupCohesion()
218 {
219 array<int> playerGroup = {};
220 array<int> players = {};
221 int groupMinSize;
222
223 if (GetGroupOfPlayersInCohesion(playerGroup, players, groupMinSize))
224 AwardXPToGroup(playerGroup, players, groupMinSize);
225
226 m_iLastGroupCount = playerGroup.Count();
227 }
228
229 //------------------------------------------------------------------------------------------------
230 int GetPlayersInCohesion(out notnull array<int> playersInCohesion)
231 {
232 array<int> playerGroup = {};
233 array<int> players = {};
234 int groupMinSize;
235
236 if (!GetGroupOfPlayersInCohesion(playerGroup, players, groupMinSize))
237 return 0;
238
239 if (playerGroup.Count() < groupMinSize)
240 return 0;
241
242 foreach (int playerIndex : playerGroup)
243 {
244 playersInCohesion.Insert(players[playerIndex]);
245 }
246
247 return playersInCohesion.Count();
248 }
249
250}
ArmaReforgerScripted GetGame()
Definition game.c:1398
void CreateAgentDistanceGraph(out array< ref array< int > > playerGraph, array< int > players, int playerCount)
void OnPlayerAddedToGroup(SCR_AIGroup aiGroup, int playerID)
void AwardXPToGroup(array< int > playerGroup, array< int > players, int groupMinSize)
bool GetGroupOfPlayersInCohesion(out notnull array< int > playerGroup, out notnull array< int > players, out int groupMinSize)
void FindGroupFromAgentDistanceGraph(out array< int > biggestGroup, const array< ref array< int > > playerGraph, int playerCount, int groupMinSize)
void CheckGroupCohesion()
void OnPlayerRemovedFromGroup(SCR_AIGroup aiGroup, int playerID)
int GetPlayersInCohesion(out notnull array< int > playersInCohesion)
SCR_AIGroupSettingsComponentClass m_Group
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
SCR_BaseGameMode GetGameMode()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition DbgUI.c:66
proto external GenericComponent FindComponent(typename typeName)
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
Definition Math.c:13
int GetPlayerCount(bool checkMasterAndSlaves=false)
static ScriptInvoker GetOnPlayerRemoved()
static ScriptInvoker GetOnPlayerAdded()
SCR_FieldOfViewSettings Attribute