Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_CaptureArea.c
Go to the documentation of this file.
1 [EntityEditorProps(category: "GameScripted/GameMode", description: "Area that provides basic events and api to serve as a captureable area.")]
3 {
4 };
5 
7 void CaptureAreaCharacterEventDelegate(SCR_CaptureArea area, Faction affiliatedFaction, IEntity character);
9 typedef ScriptInvokerBase<CaptureAreaCharacterEventDelegate> CaptureAreaEvent;
10 
12 void CaptureAreaOwnerFactionEventDelegate(SCR_CaptureArea area, Faction previousOwner, Faction newOwner);
14 typedef ScriptInvokerBase<CaptureAreaOwnerFactionEventDelegate> CaptureAreaOwnershipEvent;
15 
16 //------------------------------------------------------------------------------------------------
23 class SCR_CaptureArea : ScriptedGameTriggerEntity
24 {
30  protected ref map<Faction, ref array<SCR_ChimeraCharacter>> m_mOccupants = new map<Faction, ref array<SCR_ChimeraCharacter>>();
31 
33  protected ref CaptureAreaEvent m_pOnCharacterEnter = new CaptureAreaEvent();
34 
35  //------------------------------------------------------------------------------------------------
37  CaptureAreaEvent GetCharacterEnterInvoker()
38  {
39  return m_pOnCharacterEnter;
40  }
41 
43  protected ref CaptureAreaEvent m_pOnCharacterExit = new CaptureAreaEvent();
44 
45  //------------------------------------------------------------------------------------------------
47  CaptureAreaEvent GetCharacterExitInvoker()
48  {
49  return m_pOnCharacterExit;
50  }
51 
53  protected ref CaptureAreaOwnershipEvent m_pOnOwnershipChanged = new CaptureAreaOwnershipEvent();
54 
55  //------------------------------------------------------------------------------------------------
57  CaptureAreaOwnershipEvent GetOwnershipChangedEvent()
58  {
59  return m_pOnOwnershipChanged;
60  }
61 
63  protected Faction m_pOwnerFaction;
65  Faction GetOwningFaction() { return m_pOwnerFaction; }
66 
68  protected RplComponent m_pRplComponent;
69 
70  //------------------------------------------------------------------------------------------------
72  protected override void OnInit(IEntity owner)
73  {
74  // Do not spam messages outside of playmode,
75  // these might not be relevant (yet) also
76  // there is no need to initialize the entity (just yet)
77  if (!GetGame().InPlayMode())
78  return;
79 
80  // Mandatory, cannot work without factions
81  FactionManager factionManager = GetGame().GetFactionManager();
82  if (!factionManager)
83  {
84  Debug.Error("No faction manager present in the world! Capture area will malfunction!");
85  return;
86  }
87 
88  // Neccessary to determine replication logic
89  m_pRplComponent = RplComponent.Cast(FindComponent(RplComponent));
90  if (!m_pRplComponent)
91  {
92  Debug.Error("SCR_CaptureArea requires RplComponent to function!");
93  return;
94  }
95 
96  // Enable OnFrame event mask
97  SetEventMask(EntityEvent.FRAME);
98 
99  array<Faction> availableFactions = {};
100  factionManager.GetFactionsList(availableFactions);
101 
102  // Fetch available actions and preallocate map arrays
103  foreach (Faction faction : availableFactions)
104  m_mOccupants.Insert(faction, new array<SCR_ChimeraCharacter>());
105  }
106 
110  protected override bool RplLoad(ScriptBitReader reader)
111  {
112  int factionIndex = -1;
113  reader.ReadInt(factionIndex);
114 
115  Faction ownerFaction;
116  if (factionIndex != -1)
117  ownerFaction = GetGame().GetFactionManager().GetFactionByIndex(factionIndex);
118 
119  m_pOwnerFaction = ownerFaction;
120  return true;
121  }
122 
127  protected override bool RplSave(ScriptBitWriter writer)
128  {
129  int factionIndex = -1;
130  if (m_pOwnerFaction)
131  factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_pOwnerFaction);
132 
133  writer.WriteInt(factionIndex);
134  return true;
135  }
136 
137  //------------------------------------------------------------------------------------------------
139  protected override bool ScriptedEntityFilterForQuery(IEntity ent)
140  {
141  // Filter for characters only
142  SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(ent);
143  if (!character)
144  return false;
145 
146  // That are alive.
147  return !character.GetCharacterController().IsDead();
148  }
149 
150  //------------------------------------------------------------------------------------------------
152  protected override void OnActivate(IEntity ent)
153  {
154  if (!m_mOccupants)
155  return;
156 
157  SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(ent);
158  if (!character)
159  return;
160 
161  Faction faction = character.GetFaction();
162  if (!faction)
163  return;
164 
165  if (faction && !m_mOccupants[faction].Contains(character))
166  {
167  m_mOccupants[faction].Insert(character);
168  OnCharacterEntered(faction, character);
169  }
170  }
171 
172  //------------------------------------------------------------------------------------------------
174  protected event void OnCharacterEntered(Faction faction, SCR_ChimeraCharacter character)
175  {
176  m_pOnCharacterEnter.Invoke(this, faction, character);
177  }
178 
179  //------------------------------------------------------------------------------------------------
181  protected override void OnDeactivate(IEntity ent)
182  {
183  SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(ent);
184  Faction faction = character.GetFaction();
185 
186  if (faction)
187  {
188  m_mOccupants[faction].RemoveItem(character);
189  OnCharacterExit(faction, character);
190  }
191  }
192 
193  //------------------------------------------------------------------------------------------------
195  protected event void OnCharacterExit(Faction faction, SCR_ChimeraCharacter character)
196  {
197  m_pOnCharacterExit.Invoke(this, faction, character);
198  }
199 
200  //------------------------------------------------------------------------------------------------
207  int GetOccupants(Faction faction, notnull array<SCR_ChimeraCharacter> outCharacters)
208  {
209  array<SCR_ChimeraCharacter> characters = m_mOccupants[faction];
210  if (!characters || characters.IsEmpty())
211  return 0;
212 
213  outCharacters.Copy(characters);
214  return characters.Count();
215  }
216 
217  //------------------------------------------------------------------------------------------------
223  int GetOccupantsCount(Faction faction)
224  {
225  return m_mOccupants[faction].Count();
226  }
227 
228  //------------------------------------------------------------------------------------------------
235  protected Faction EvaluateOwnerFaction()
236  {
237  // Fetch all available factions
238  array<Faction> availableFactions = {};
239  GetGame().GetFactionManager().GetFactionsList(availableFactions);
240 
241  int maxCount;
242  Faction maxFaction;
243  int occupantsCount;
244  foreach (Faction faction : availableFactions)
245  {
246  occupantsCount = GetOccupantsCount(faction);
247  if (occupantsCount == 0)
248  continue;
249 
250  if (occupantsCount > maxCount)
251  {
252  maxCount = occupantsCount;
253  maxFaction = faction;
254  }
255  }
256 
257  // With no alive occupants in the area, no faction can
258  // be deemed as the capturing one
259  if (maxCount == 0)
260  return null;
261 
262  return maxFaction;
263  }
264 
265  //------------------------------------------------------------------------------------------------
269  protected override event void OnFrame(IEntity owner, float timeSlice)
270  {
271  super.OnFrame(owner, timeSlice);
272 
273  // Since trigger can be out of sync with character states,
274  // filter out dead characters if any are left in the collection
275  foreach (Faction faction, array<SCR_ChimeraCharacter> characters : m_mOccupants)
276  {
277  for (int i = characters.Count() - 1; i >= 0; --i)
278  {
279  SCR_ChimeraCharacter occupant = characters[i];
280  if (!occupant || occupant.GetCharacterController().IsDead())
281  {
282  characters.Remove(i);
283  continue;
284  }
285  }
286  }
287 
288  // Only the authority will be updating the state,
289  // rpl component is prerequisite for this entity
290  if (!m_pRplComponent || !m_pRplComponent.IsMaster())
291  return;
292 
293  Faction newOwner = EvaluateOwnerFaction();
294  if (newOwner != m_pOwnerFaction)
295  {
296  Faction previousOwner = m_pOwnerFaction;
297  SetOwningFactionInternal(previousOwner, newOwner);
298 
299  // For the authority, this is fired straight away above,
300  // so we only send the change to all clients as broadcast
301  FactionManager factionManager = GetGame().GetFactionManager();
302  int previousIndex = factionManager.GetFactionIndex(previousOwner);
303  int newIndex = factionManager.GetFactionIndex(newOwner);
304  Rpc(Rpc_SetOwningFaction_BC, previousIndex, newIndex);
305  }
306  }
307 
308  //------------------------------------------------------------------------------------------------
310  protected void SetOwningFactionInternal(Faction previousFaction, Faction newFaction)
311  {
312  m_pOwnerFaction = newFaction;
313  OnOwningFactionChanged(previousFaction, newFaction);
314  }
315 
316  //------------------------------------------------------------------------------------------------
321  [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
322  protected void Rpc_SetOwningFaction_BC(int previousFactionIndex, int newFactionIndex)
323  {
324  FactionManager factionManager = GetGame().GetFactionManager();
325 
326  Faction previousFaction;
327  if (previousFactionIndex != -1)
328  previousFaction = factionManager.GetFactionByIndex(previousFactionIndex);
329 
330  Faction newFaction;
331  if (newFactionIndex != -1)
332  newFaction = factionManager.GetFactionByIndex(newFactionIndex);
333 
334  SetOwningFactionInternal(previousFaction, newFaction);
335  }
336 
337  //------------------------------------------------------------------------------------------------
343  protected event void OnOwningFactionChanged(Faction previousFaction, Faction newFaction)
344  {
345  m_pOnOwnershipChanged.Invoke(this, previousFaction, newFaction);
346  }
347 };
CaptureAreaOwnershipEvent
ScriptInvokerBase< CaptureAreaOwnerFactionEventDelegate > CaptureAreaOwnershipEvent
Definition: SCR_CaptureArea.c:14
CaptureAreaCharacterEventDelegate
func CaptureAreaCharacterEventDelegate
Definition: SCR_CaptureArea.c:8
EntityEditorProps
enum EQueryType EntityEditorProps(category:"GameScripted/Sound", description:"THIS IS THE SCRIPT DESCRIPTION.", color:"0 0 255 255")
Definition: SCR_AmbientSoundsComponent.c:12
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
CaptureAreaOwnerFactionEventDelegate
func CaptureAreaOwnerFactionEventDelegate
Definition: SCR_CaptureArea.c:13
func
func
Definition: SCR_AIThreatSystem.c:5
ScriptedGameTriggerEntityClass
Definition: ScriptedGameTriggerEntity.c:12
Contains
proto external sealed bool Contains(IEntity item)
Faction
Definition: Faction.c:12
CaptureAreaEvent
ScriptInvokerBase< CaptureAreaCharacterEventDelegate > CaptureAreaEvent
Definition: SCR_CaptureArea.c:9
SCR_CaptureArea
Definition: SCR_CaptureArea.c:23
SCR_CaptureAreaClass
Definition: SCR_CaptureArea.c:2
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180