Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CaptureAndHoldArea.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/GameMode/CaptureAndHold", description: "Area that awards score points when captured.")]
5
7void CaptureAreaTickEventDelegate(SCR_CaptureAndHoldArea area, Faction currentOwner, int score);
9typedef ScriptInvokerBase<CaptureAreaTickEventDelegate> CaptureAreaTickEvent;
10
14{
15 [Attribute("#AR-CAH-Area_Symbol_A", UIWidgets.EditBox, "Single character used for visualizing this area.", category: "CaptureAndHold")]
16 LocalizedString m_sAreaSymbol;
17
18 [Attribute("0 0 0", UIWidgets.EditBox, "Center of the objective in local space.", category: "CaptureAndHold", params: "inf inf 0 purposeCoords spaceEntity")]
19 vector m_vObjectiveCenter;
20
21 [Attribute("1", UIWidgets.Slider, "Duration in seconds before each point is awarded.", params: "0.1 100.0 0.1", category: "CaptureAndHold")]
22 float m_fTickRate;
23
24 [Attribute("5", UIWidgets.Slider, "Score awarded per tick.", params: "1 1000 1", category: "CaptureAndHold")]
25 int m_iScorePerTick;
26
27 [Attribute("0", UIWidgets.Slider, "Score awarded per tick when contested.", params: "0 1000 1", category: "CaptureAndHold")]
28 int m_iScorePerTickContested;
29
30 [Attribute("0.5", UIWidgets.Slider, "Percent of players needed (compared to max players) to start contesting.", params: "0 1 0.01", category: "CaptureAndHold")]
31 float m_fContestingRatio;
32
33 [Attribute("0", UIWidgets.CheckBox, "Is this area a major capture area?", category: "CaptureAndHold")]
34 bool m_bIsMajor;
35
37 float m_fTickTime;
38
41
43 protected SCR_MapDescriptorComponent m_MapDescriptor;
44
47
48 //------------------------------------------------------------------------------------------------
54
55 //------------------------------------------------------------------------------------------------
58 {
59 return GetContestingFaction() != null;
60 }
61
62 //------------------------------------------------------------------------------------------------
64 bool IsMajor()
65 {
66 return m_bIsMajor;
67 }
68
69 //------------------------------------------------------------------------------------------------
71 protected override bool RplLoad(ScriptBitReader reader)
72 {
73 super.RplLoad(reader);
74
75 int factionIndex = -1;
76 reader.ReadInt(factionIndex);
77
78 Faction contestingFaction;
79 if (factionIndex != -1)
80 contestingFaction = GetGame().GetFactionManager().GetFactionByIndex(factionIndex);
81
82 m_ContestingFaction = contestingFaction;
83
86
87 return true;
88 }
89
90 //------------------------------------------------------------------------------------------------
93 protected override bool RplSave(ScriptBitWriter writer)
94 {
95 super.RplSave(writer);
96
97 int factionIndex = -1;
99 factionIndex = GetGame().GetFactionManager().GetFactionIndex(m_ContestingFaction);
100
101 writer.WriteInt(factionIndex);
102 return true;
103 }
104
105 //------------------------------------------------------------------------------------------------
107 protected void SetContestingFactionInternal(Faction previousFaction, Faction newFaction)
108 {
109 m_ContestingFaction = newFaction;
110 OnContestingFactionChanged(previousFaction, newFaction);
111 }
112
113 //------------------------------------------------------------------------------------------------
116 [RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
117 protected void Rpc_SetContestingFaction_BC(int previousFactionIndex, int newFactionIndex)
118 {
119 FactionManager factionManager = GetGame().GetFactionManager();
120
121 Faction previousFaction;
122 if (previousFactionIndex != -1)
123 previousFaction = factionManager.GetFactionByIndex(previousFactionIndex);
124
125 Faction newFaction;
126 if (newFactionIndex != -1)
127 newFaction = factionManager.GetFactionByIndex(newFactionIndex);
128
129 SetContestingFactionInternal(previousFaction, newFaction);
130 }
131
132 //------------------------------------------------------------------------------------------------
138
139 //------------------------------------------------------------------------------------------------
142 {
143 return m_iScorePerTick;
144 }
145
146 //------------------------------------------------------------------------------------------------
149 {
150 return m_sAreaSymbol;
151 }
152
153 //------------------------------------------------------------------------------------------------
156 {
157 return m_vObjectiveCenter;
158 }
159
160 //------------------------------------------------------------------------------------------------
163 {
164 return CoordToParent(m_vObjectiveCenter);
165 }
166
167 //------------------------------------------------------------------------------------------------
170 {
171 return SCR_BaseGameMode.Cast(GetGame().GetGameMode());
172 }
173
174 //------------------------------------------------------------------------------------------------
180
181 //------------------------------------------------------------------------------------------------
183 protected override void OnInit(IEntity owner)
184 {
185 super.OnInit(owner);
186
187 // Supress messages out of playmode, order of things is not quite guaranteed here
188 if (!GetGame().InPlayMode())
189 return;
190
191 // Register self in manager
192 SCR_CaptureAndHoldManager parentManager = SCR_CaptureAndHoldManager.GetAreaManager();
193 if (!parentManager)
194 {
195 Print("CaptureAndHoldArea cannot find SCR_CaptureAndHoldManager! Functionality might be limited!", LogLevel.WARNING);
196 return;
197 }
198
199 parentManager.RegisterArea(this);
200
201 // If map descriptor is present, initialize it
202 m_MapDescriptor = SCR_MapDescriptorComponent.Cast(FindComponent(SCR_MapDescriptorComponent));
203 if (m_MapDescriptor)
204 {
207 }
208
210 {
211 Print("CaptureAndHoldArea cannot find SCR_BaseScoringSystemComponent! Points will not be awarded!", LogLevel.WARNING);
212 }
213 }
214
215 //------------------------------------------------------------------------------------------------
218 protected void InitializeMapDescriptor(SCR_MapDescriptorComponent target)
219 {
220 MapItem item = target.Item();
221 if (!item)
222 return;
223
224 MapDescriptorProps props = item.GetProps();
225 if (!props)
226 return;
227
228 props.SetIconSize(0.65, 0.65, 0.65);
229 props.SetTextSize(32, 32, 32);
230 props.SetTextBold();
231 props.SetFrontColor(Color.White);
232 props.SetTextColor(Color.White);
233 props.SetTextOffsetX(-10);
234 props.SetTextOffsetY(-16.5);
235 props.Activate(true);
236 props.SetFont("{EABA4FE9D014CCEF}UI/Fonts/RobotoCondensed/RobotoCondensed_Bold.fnt");
237 item.SetProps(props);
238 item.SetDisplayName(GetAreaSymbol());
240 item.SetPos(xyz[0], xyz[2]);
241 item.SetVisible(true);
242 }
243
244 //------------------------------------------------------------------------------------------------
247 protected void UpdateMapDescriptor(SCR_MapDescriptorComponent target)
248 {
249 if (!target)
250 return;
251
252 Color color = Color.FromRGBA(249, 210, 103, 255);
253 bool friendly = false;
254 if (m_pOwnerFaction)
255 {
256 if (IsContested())
257 {
258 float val01 = Math.Sin( GetWorld().GetWorldTime() * 0.01 ) * 0.5 + 0.5;
259 color.Lerp(m_pOwnerFaction.GetFactionColor(), val01);
260 }
261 else
262 {
263 color = m_pOwnerFaction.GetFactionColor();
264 }
265 }
266
267 MapItem mapItem = target.Item();
268 if (!mapItem)
269 return;
270
271 MapDescriptorProps props = mapItem.GetProps();
272 if (!props)
273 return;
274
275 props.SetFrontColor(color);
276 props.SetTextColor(color);
277
278 props.Activate(true);
279 mapItem.SetProps(props);
280 }
281
282 //------------------------------------------------------------------------------------------------
284 protected override void OnFrame(IEntity owner, float timeSlice)
285 {
286 super.OnFrame(owner, timeSlice);
287
288 // Update map descriptor
291
292 // Only the authority shall awards points
293 if (!m_pRplComponent || !m_pRplComponent.IsMaster())
294 return;
295
296 // Do not update unless the game is started
297 // or if no faction holds the point
298 if (!GetGameMode().IsRunning() || !GetOwningFaction())
299 {
300 m_fTickTime = 0.0;
301 return;
302 }
303
304 // Update tick time, in case time step is too large,
305 // multiple ticks can occur within a single frame
306 // TODO: Design question @Jesper:
307 // tick even with no owner, or only tick when owning faction holds and reset?
308 // additionally this logic might be reworked, so keeping it simple now
309 m_fTickTime += timeSlice;
310 while (m_fTickTime >= m_fTickRate)
311 {
312 m_fTickTime -= m_fTickRate;
313 OnTick();
314 }
315 }
316
317 //------------------------------------------------------------------------------------------------
320 protected void OnTick()
321 {
322 // Callback is fired, if a faction is owning this point
323 Faction owningFaction = GetOwningFaction();
324
325 bool isContested = IsContested();
326
327 // Award no score if contesting
328 int awardedScore;
329 if (!isContested)
330 awardedScore = GetScorePerTick();
331
332 m_OnTickEvent.Invoke(this, owningFaction, awardedScore);
333
334 // No scoring at all
335 if (isContested)
336 return;
337
338 // Must have scoring system to award points
340 if (!scoringSystem)
341 return;
342
343 // Add score to faction
344 scoringSystem.AddFactionObjective(owningFaction, awardedScore);
345 // And additionally to all players of given faction in this point
346
347 array<SCR_ChimeraCharacter> occupants = {};
348 int count = GetOccupants(owningFaction, occupants);
349 for (int i = 0; i < count; ++i)
350 {
351 int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(occupants[i]);
352 // Not a player
353 if (playerId <= 0)
354 continue;
355
356 // Award player score, but do not propagate to faction - faction is already awarded
357 scoringSystem.AddObjective(playerId, awardedScore, false);
358 }
359 }
360
361 //------------------------------------------------------------------------------------------------
364 protected void DoSetContestingFaction(Faction previousFaction, Faction newFaction)
365 {
366 // For the authority, this is fired straight away above,
367 // so we only send the change to all clients as broadcast
368 FactionManager factionManager = GetGame().GetFactionManager();
369 int previousIndex = factionManager.GetFactionIndex(previousFaction);
370 int newIndex = -1;
371 if (newFaction)
372 newIndex = factionManager.GetFactionIndex(newFaction);
373
374 SetContestingFactionInternal(previousFaction, newFaction);
375 Rpc(Rpc_SetContestingFaction_BC, previousIndex, newIndex);
376 }
377
378 //------------------------------------------------------------------------------------------------
380 protected override Faction EvaluateOwnerFaction()
381 {
382 Faction owningFaction = super.EvaluateOwnerFaction();
383 if (!owningFaction)
384 {
385 // Clear contesting faction, there is no owner, therefore there can be no contester
388
389
390 // If persistent capture areas are allowed, instead of clearing the owning faction,
391 // we simply return the last known (if any) faction instead.
392 SCR_CaptureAndHoldManager manager = SCR_CaptureAndHoldManager.GetAreaManager();
393 if (manager && manager.GetIsAreaFactionPersistent())
394 {
395 return GetOwningFaction();
396 }
397
398 return null;
399 }
400
401 // If the area is already owned by a faction (m_pOwnerFaction), do not
402 // update ownership if the new evaluated faction (owningFaction) has
403 // equal number of players in the area to the previous owner
404 if (owningFaction && m_pOwnerFaction)
405 {
407 owningFaction = m_pOwnerFaction;
408 }
409
410 // If there is an owner faction, see how many occupants of given faction
411 int ownerCount = GetOccupantsCount(owningFaction);
412
413 Faction contestingFaction;
414 int contestingCount;
415 foreach (Faction faction, array<SCR_ChimeraCharacter> occupants : m_mOccupants)
416 {
417 if (faction == owningFaction)
418 continue;
419
420 // Find faction that has second most occupants
421 int occupantCount = GetOccupantsCount(faction);
422 if (occupantCount > contestingCount)
423 {
424 contestingCount = occupantCount;
425 contestingFaction = faction;
426 }
427 }
428
429 // Contesting faction needs at least n players to pass the contesting ratio
430 float minContestingCount = m_fContestingRatio * ownerCount;
431 if ((float)contestingCount >= minContestingCount)
432 {
433 // We are contesting
434 if (m_ContestingFaction != contestingFaction)
436 }
437 else
438 {
439 if (m_ContestingFaction != null)
441 }
442
443 return owningFaction;
444 }
445
446 //------------------------------------------------------------------------------------------------
449 bool IsCharacterInside(SCR_ChimeraCharacter character)
450 {
451 if (!character)
452 return false;
453
454 Faction faction = character.GetFaction();
455 if (!faction)
456 return false;
457
458 int indexOf = m_mOccupants[faction].Find(character);
459 return indexOf != -1;
460 }
461
462 //------------------------------------------------------------------------------------------------
466 protected event void OnContestingFactionChanged(Faction previousFaction, Faction newFaction)
467 {
468 if (m_MapDescriptor)
470 }
471
472 //------------------------------------------------------------------------------------------------
476 protected override void OnOwningFactionChanged(Faction previousFaction, Faction newFaction)
477 {
478 super.OnOwningFactionChanged(previousFaction, newFaction);
479
480 if (m_MapDescriptor)
482 }
483
484 //------------------------------------------------------------------------------------------------
486 protected void ~SCR_CaptureAndHoldArea()
487 {
488 // Far from ideal, OnDelete would be better
489
490 // Register self in manager
491 SCR_CaptureAndHoldManager parentManager = SCR_CaptureAndHoldManager.GetAreaManager();
492 if (!parentManager)
493 return;
494
495 parentManager.UnregisterArea(this);
496 }
497}
ArmaReforgerScripted GetGame()
Definition game.c:1398
ScriptInvokerBase< CaptureAreaTickEventDelegate > CaptureAreaTickEvent
func CaptureAreaTickEventDelegate
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
Definition Color.c:13
Definition Math.c:13
SCR_BaseScoringSystemComponent GetScoringSystemComponent()
CaptureAreaTickEvent GetOnTickInvoker()
Returns invoker that is invoked when this area ticks (awards score).
override bool RplSave(ScriptBitWriter writer)
void ~SCR_CaptureAndHoldArea()
Unregisters self from parent manager.
event void OnContestingFactionChanged(Faction previousFaction, Faction newFaction)
ref CaptureAreaTickEvent m_OnTickEvent
Callback for when a tick event is raised by this area.
void UpdateMapDescriptor(SCR_MapDescriptorComponent target)
bool IsMajor()
Returns true if this area is marked as a major objective.
override void OnOwningFactionChanged(Faction previousFaction, Faction newFaction)
LocalizedString GetAreaSymbol()
Returns the short "symbolic" one-character name of this area.
vector GetWorldObjectiveCenter()
Returns objective center in world space.
SCR_BaseGameMode GetGameMode()
Utility method - returns current scripted game mode.
void Rpc_SetContestingFaction_BC(int previousFactionIndex, int newFactionIndex)
SCR_MapDescriptorComponent m_MapDescriptor
Attached map descriptor component used for visualization (if any) or null if none.
bool IsCharacterInside(SCR_ChimeraCharacter character)
override Faction EvaluateOwnerFaction()
Handles owning and contesting changes based on defined parameters.
override void OnFrame(IEntity owner, float timeSlice)
Updates the area and awards points if held.
void SetContestingFactionInternal(Faction previousFaction, Faction newFaction)
Sets internal owner faction and raises corresponding callback.
void InitializeMapDescriptor(SCR_MapDescriptorComponent target)
SCR_BaseScoringSystemComponent GetScoringSystemComponent()
Returns scoring system attached to current gamemode (if any) or null otherwise.
override void OnInit(IEntity owner)
Initialize this area and register it to parent manager.
Faction GetContestingFaction()
Returns the faction that currently owns the area or null if none.
bool IsContested()
Returns true if this area is being contested.
Faction m_ContestingFaction
The faction that currently attacking/contesting this point in relation to the owner faction.
override bool RplLoad(ScriptBitReader reader)
Called when Item is initialized from replication stream. Carries the data from Master.
vector GetLocalObjectiveCenter()
Returns objective center in local space relative to the area.
int GetScorePerTick()
Returns score awarded per area tick.
void DoSetContestingFaction(Faction previousFaction, Faction newFaction)
RplComponent m_pRplComponent
Replication component of this entity.
ref map< Faction, ref array< SCR_ChimeraCharacter > > m_mOccupants
Faction GetOwningFaction()
Returns the faction that currently owns the area or null if none.
int GetOccupantsCount(Faction faction)
int GetOccupants(Faction faction, notnull array< SCR_ChimeraCharacter > outCharacters)
Faction m_pOwnerFaction
The faction that currently owns this area.
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
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