Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_BaseGameMode.c
Go to the documentation of this file.
1 #ifdef GMSTATS
2 #define GM_AI_STATS
3 #endif
4 #ifdef AISTATS
5 #define GM_AI_STATS
6 #endif
7 
13 {
14 };
15 
17 //------------------------------------------------------------------------------------------------
18 /*
19  SCR_BaseGameMode
20 
21 Brief:
22  SCR_BaseGameMode is the skeleton of all game modes which connects some of the critical aspects of spawning.
23 
24 Important:
25  A. Components and expansion:
26  1. SCR_BaseGameMode automatically gathers all attached components of SCR_BaseGameModeComponent type.
27  These can be used to receive events from the game mode and expand game mode functionality in modular blocks.
28 
29  2. SCR_RespawnSystemComponent is a component that allows to store and select player faction, loadout and spawn points
30  This system is closely tied to game modes and also requires FactionManager or LoadoutManager in the world.
31 
32  3. SCR_RespawnHandlerComponent is a component that provides a game mode with a way of respawning.
33  These can be either very generic (automatic, menu selection) and interchangable or completely game mode specific.
34 
35  4. Additional components like
36  SCR_RespawnTimerComponent: That allows to add a timer between each respawn
37  SCR_ScoringSystemComponent: That allows handling of score when a player kills or is killed
38 
39 
40  If you want to make a system which only requires to hook on game mode events, SCR_BaseGameMode is most likely the way to go.
41  Inherit the component and implement methods which you require. If you need to have a very game specific implementation that
42  cannot work standalone you will have to inherit SCR_BaseGameMode and plug the communication yourself.
43 
44 
45  B. Instances and logic:
46  1. SCR_BaseGameMode is a unique entity in the world, there can currently be only one game mode.
47  2. SCR_RespawnSystemComponent is a unique component attached to the game mode, there can currently be only one respawn system.
48  3. SCR_RespawnHandlerComponent is a unique component attached to the game mode, there can currently be only one respawn handler.
49  4. SCR_RespawnComponent is a component attached to individual PlayerController instances.
50  Due to the nature of PlayerController, only the server can access all RespawnComponent(s).
51  The local client will always be only to access their local RespawnComponent.
52 
53  For the local component you can use GetGame().GetPlayerController().GetRespawnComponent();
54  For other clients as the authority you can use GetGame().GetPlayerManager().GetPlayerRespawnComponent( int playerId );
55 
56  This component serves as communication between the authority and client for the SCR_RespawnSystemComponent.
57  If you need to request a faction, loadout or spawn point selection as the client, navigate through the component.
58 
59  If you need to SET a faction, loadout or spawn point as the AUTHORITY, use SCR_RespawnSystemComponent's
60  DoSetPlayerFaction, DoSetPlayerLoadout and DoSetPlayerSpawnPoint method(s).
61 
62  If you need to convert object instances to their id/indices, you can use SCR_RespawnSystemComponent's
63  GetFactionIndex, GetLoadoutIndex, GetSpawnPointIndex method(s) and/or
64  GetFactionByIndex, GetLoadoutByIndex, GetSpawnPointByIdentity.
65 
66 
67  C. Game State
68  There are three game states in total that you can use, two of which are optional.
69  1. Pre-game:
70  This state is automatically skipped unless a
71  SCR_BaseGameModeStateComponent that has SCR_EGameModeState.PREGAME as its affiliated state
72  is attached to the game mode.
73 
74  The SCR_PreGameGameModeStateComponent can be used to allow a time-based pre-game duration.
75 
76  2. Game
77  This is the core game loop.
78 
79  By default this state is infinite, unless a
80  SCR_BaseGameModeStateComponent that has SCR_EGameModeState.GAME as its affiliated state
81  is attached to the game mode with a duration set.
82 
83  The SCR_GameGameModeStateComponent can be used to allow a time-based pre-game duration.
84 
85  3. Post-game
86  This is your game-over state, you can automatically transition into new world, restart the session,
87  have player voting, display scoreboard or end-game screens, as desired.
88 
89  In addition this transition carries along SCR_GameModeEndData, providing the authority and all
90  clients with additional data that can notify the gamemode about e.g. win condition, or end reason
91  as implemented per game mode.
92 
93  This state can also have its logic expanded similarly to the Pre-game by using
94  SCR_BaseGameModeStateComponent that has SCR_EGameModeState.POSTGAME as its affiliated state
95  attached to the game mode.
96 
97  The SCR_PostGameGameModeStateComponent can be used for this.
98 
99 
100  You can always retrieve current game state by calling GetState() (see SCR_GameModeState)
101  or IsRunning() if you're interested in the core game loop only.
102 
103  On each state change SCR_BaseGameMode.OnGameStateChanged() is called on both the server and all clients.
104  In additionaly as implemented in this class it will automatically call OnGameModeStart() and OnGameModeEnd()
105  based on the state the game is transitioning into.
106 */
107 
108 //------------------------------------------------------------------------------------------------
109 //~ ScriptInvokers
110 void SCR_BaseGameMode_OnPlayerDisconnected(int playerId, KickCauseCode cause = KickCauseCode.NONE, int timeout = -1);
112 
113 void SCR_BaseGameMode_OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer);
115 
116 //~ Generic Event that sends over player ID
117 void SCR_BaseGameMode_PlayerId(int playerId);
119 
120 //~ Generic event that sends over player ID and Entity
121 void SCR_BaseGameMode_PlayerIdAndEntity(int playerId, IEntity player);
123 
124 //~ On Player role changed
125 void SCR_BaseGameMode_OnPlayerRoleChanged(int playerId, EPlayerRole roleFlags);
127 
128 void SCR_BaseGameMode_OnResourceEnabledChanged(array<EResourceType> disabledResourceTypes);
130 
131 void OnPreloadFinished();
133 typedef ScriptInvokerBase<OnPreloadFinished> OnPreloadFinishedInvoker;
134 
135 
136 //------------------------------------------------------------------------------------------------
137 class SCR_BaseGameMode : BaseGameMode
138 {
139  #ifdef ENABLE_DIAG
140  #define GAME_MODE_DEBUG
141  #endif
142 
143  #ifdef GAME_MODE_DEBUG
144  static bool s_DebugRegistered = false;
145  #endif
146 
147  const static string WB_GAME_MODE_CATEGORY = "Game Mode";
148 
149  protected ref ScriptInvoker Event_OnGameStart = new ScriptInvoker();
150  protected ref ScriptInvoker m_OnGameEnd = new ScriptInvoker();
151 
152  //~ Player events
153  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerAuditSuccess = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
154  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerAuditFail = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
155  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerAuditTimeouted = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
156  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerAuditRevived = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
157  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerConnected = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
158  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerId> m_OnPlayerRegistered = new ScriptInvokerBase<SCR_BaseGameMode_PlayerId>();
159  protected ref ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected> m_OnPlayerDisconnected = new ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected>();
160  protected ref ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected> m_OnPostCompPlayerDisconnected = new ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected>(); //~ Called after the GameMode Components are notified that a player was disconnected
161  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity> m_OnPlayerSpawned = new ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity>();
162  protected ref ScriptInvokerBase<SCR_BaseGameMode_OnPlayerKilled> m_OnPlayerKilled = new ScriptInvokerBase<SCR_BaseGameMode_OnPlayerKilled>();
163  protected ref ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity> m_OnPlayerDeleted = new ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity>();
164  protected ref ScriptInvokerBase<SCR_BaseGameMode_OnPlayerRoleChanged> m_OnPlayerRoleChange = new ScriptInvokerBase<SCR_BaseGameMode_OnPlayerRoleChanged>();
165 
166  protected ref ScriptInvoker m_OnWorldPostProcess = new ScriptInvoker();
167  protected ref ScriptInvoker m_OnControllableSpawned = new ScriptInvoker();
168  protected ref ScriptInvoker m_OnControllableDestroyed = new ScriptInvoker();
169  protected ref ScriptInvoker m_OnControllableDeleted = new ScriptInvoker();
170  protected ref ScriptInvoker m_OnGameModeEnd = new ScriptInvoker();
171 
172  protected ref ScriptInvokerBase<SCR_BaseGameMode_OnResourceEnabledChanged> m_OnResourceTypeEnabledChanged;
173 
174  //-----------------------------------------
175  //
176  // World Editor attributes meant for Debug or Testing
177  //
178  [Attribute("0", uiwidget: UIWidgets.Flags, "Test Game Flags for when you run mission via WE.", "", ParamEnumArray.FromEnum(EGameFlags), WB_GAME_MODE_CATEGORY)]
179  protected EGameFlags m_eTestGameFlags;
180 
181  [Attribute("1", uiwidget: UIWidgets.CheckBox, "When false, then Game mode need to handle its very own spawning. If true, then simple default logic is used to spawn and respawn automatically.", category: WB_GAME_MODE_CATEGORY)]
182  protected bool m_bAutoPlayerRespawn;
183 
184  [Attribute("1", uiwidget: UIWidgets.CheckBox, "When true, allows players to freely swap their faction after initial assignment.", category: WB_GAME_MODE_CATEGORY)]
185  protected bool m_bAllowFactionChange;
186 
187  [Attribute("30", UIWidgets.Slider, params: "0 600 1", desc: "Time in seconds after which the mission is reloaded upon completion or 0 to disable it.", category: WB_GAME_MODE_CATEGORY)]
188  private float m_fAutoReloadTime;
189 
190  //-----------------------------------------
191  //
192  // Game End Screen States info
193  //
194 
196  [RplProp(onRplName: "OnGameStateChanged")]
197  private SCR_EGameModeState m_eGameState = SCR_EGameModeState.PREGAME;
198 
200  [RplProp()]
201  private ref SCR_GameModeEndData m_pGameEndData = new SCR_GameModeEndData();
202 
203  [Attribute("1", uiwidget: UIWidgets.CheckBox, "If checked the elapsed time will only advance if at least one player is present on the server.", category: WB_GAME_MODE_CATEGORY)]
204  protected bool m_bAdvanceTimeRequiresPlayers;
205 
210  [RplProp(condition: RplCondition.NoOwner)]
211  protected float m_fTimeElapsed;
212 
214  [RplProp()]
215  protected bool m_bAllowControls = true;
216 
218  protected float m_fTimeCorrectionInterval = 10.0;
219 
221  protected float m_fLastTimeCorrection;
222 
224  [RplProp()]
225  protected bool m_bIsHosted;
226 
227  //-----------------------------------------
228  //
229  // Required components
230  //
231  protected RplComponent m_RplComponent;
232  protected SCR_GameModeHealthSettings m_pGameModeHealthSettings;
233  protected SCR_RespawnSystemComponent m_pRespawnSystemComponent;
234  protected SCR_BaseScoringSystemComponent m_ScoringSystemComponent;
235  protected SCR_RespawnTimerComponent m_RespawnTimerComponent;
236 
240  protected ref array<SCR_BaseGameModeComponent> m_aAdditionalGamemodeComponents = new array<SCR_BaseGameModeComponent>();
241 
243  protected ref map<int, vector> m_mPlayerSpawnPosition = new map<int, vector>();
244 
246  protected ref map<SCR_EGameModeState, SCR_BaseGameModeStateComponent> m_mStateComponents = new map<SCR_EGameModeState, SCR_BaseGameModeStateComponent>();
247 
249  [Attribute("1", category: WB_GAME_MODE_CATEGORY)]
250  protected bool m_bUseSpawnPreload;
251 
252  protected ref SCR_SpawnPreload m_SpawnPreload;
253  protected ref OnPreloadFinishedInvoker m_OnPreloadFinished;
254 
255  //~ Any Resource types that is set here is a disabled resource type
256  [Attribute(desc: "List of disabled Resource Types in the GameMode.", uiwidget: UIWidgets.SearchComboBox, enums: ParamEnumArray.FromEnum(EResourceType), category: "Game Mode"), RplProp(onRplName: "OnResourceTypeEnabledChanged")]
257  protected ref array<EResourceType> m_aDisabledResourceTypes;
258 
259  //~ Time stamp when end game was called
260  protected WorldTimestamp m_GameEndTimeStamp = null;
261 
262  //------------------------------------------------------------------------------------------------
264  bool IsResourceTypeEnabled(EResourceType resourceType = EResourceType.SUPPLIES)
265  {
266  return !m_aDisabledResourceTypes.Contains(resourceType);
267  }
268 
269  //------------------------------------------------------------------------------------------------
272  int GetDisabledResourceTypes(inout notnull array<EResourceType> disabledResourceTypes)
273  {
274  disabledResourceTypes.Copy(m_aDisabledResourceTypes);
275  return disabledResourceTypes.Count();;
276  }
277 
278  //------------------------------------------------------------------------------------------------
283  void SetResourceTypeEnabled(bool enable, EResourceType resourceType = EResourceType.SUPPLIES, int playerID = -1)
284  {
285  int index = m_aDisabledResourceTypes.Find(resourceType);
286 
287  //~ Already Enabled/Disabled
288  if ((index < 0) == enable)
289  return;
290 
291  if (!enable)
292  m_aDisabledResourceTypes.Insert(resourceType);
293  else
295 
296  Replication.BumpMe();
297 
298  //~ Call on resourceType changed for server as well
299  if (IsMaster())
300  OnResourceTypeEnabledChanged();
301 
302  if (resourceType == EResourceType.SUPPLIES)
303  {
304  if (enable)
305  SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_ENABLE_GLOBAL_SUPPLY_USAGE, playerID);
306  else
307  SCR_NotificationsComponent.SendToEveryone(ENotification.EDITOR_ATTRIBUTES_DISABLE_GLOBAL_SUPPLY_USAGE, playerID);
308  }
309  }
310 
311  //------------------------------------------------------------------------------------------------
313  protected void OnResourceTypeEnabledChanged()
314  {
317  }
318 
319  //------------------------------------------------------------------------------------------------
321  ScriptInvokerBase<SCR_BaseGameMode_OnResourceEnabledChanged> GetOnResourceTypeEnabledChanged()
322  {
324  m_OnResourceTypeEnabledChanged = new ScriptInvokerBase<SCR_BaseGameMode_OnResourceEnabledChanged>();
325 
327  }
328 
329  //------------------------------------------------------------------------------------------------
330  bool CanStartSpawnPreload()
331  {
332  ChimeraWorld world = GetGame().GetWorld();
333  return (!world.IsGameTimePaused() && m_bUseSpawnPreload);
334  }
335 
336  //------------------------------------------------------------------------------------------------
341  bool IsRunning()
342  {
343  return m_eGameState == SCR_EGameModeState.GAME;
344  }
345 
346  //------------------------------------------------------------------------------------------------
351  SCR_EGameModeState GetState()
352  {
353  return m_eGameState;
354  }
355 
356  //------------------------------------------------------------------------------------------------
360  sealed bool IsMaster()
361  {
362  return (!m_RplComponent || m_RplComponent.IsMaster());
363  }
364 
365  //------------------------------------------------------------------------------------------------
370  float GetElapsedTime()
371  {
372  return m_fTimeElapsed;
373  }
374 
375  //------------------------------------------------------------------------------------------------
380  float GetTimeLimit()
381  {
382  SCR_BaseGameModeStateComponent stateComponent = GetStateComponent(SCR_EGameModeState.GAME);
383  if (stateComponent)
384  return stateComponent.GetDuration();
385 
386  return 0.0;
387  }
388 
389  //------------------------------------------------------------------------------------------------
394  float GetRemainingTime()
395  {
396  float timeLimit = GetTimeLimit();
397  if (!IsRunning() || timeLimit <= 0)
398  return -1;
399 
400  float time = timeLimit - GetElapsedTime();
401  if (time < 0)
402  time = 0;
403 
404  return time;
405  }
406 
407  //------------------------------------------------------------------------------------------------
411  bool IsHosted()
412  {
413  return m_bIsHosted;
414  }
415 
416  //------------------------------------------------------------------------------------------------
421  protected void OnGameStateChanged()
422  {
423  SCR_EGameModeState newState = GetState();
424  Print("SCR_BaseGameMode::OnGameStateChanged = " + SCR_Enum.GetEnumName(SCR_EGameModeState, newState));
425 
426  //We handle the OnGameModeEnd and OnGameModeStart events here
427  //Because this is the only replicated call.
428  //And we propagate it to the components here for robusty in case of overriding those methods
429  switch (newState)
430  {
431  case SCR_EGameModeState.POSTGAME:
432  OnGameModeEnd(m_pGameEndData);
433  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
434  {
435  component.OnGameModeEnd(m_pGameEndData);
436  }
437  break;
438 
439  case SCR_EGameModeState.GAME:
440  OnGameModeStart();
441  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
442  {
443  component.OnGameModeStart();
444  }
445  break;
446  }
447 
448  // Dispatch events
449  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
450  {
451  component.OnGameStateChanged(newState);
452  }
453  }
454 
455  //------------------------------------------------------------------------------------------------
456  void CachePlayerSpawnPosition(int playerID, vector position)
457  {
458  m_mPlayerSpawnPosition.Set(playerID, position);
459  }
460 
461  //------------------------------------------------------------------------------------------------
466  SCR_RespawnSystemComponent GetRespawnSystemComponent()
467  {
468  return m_pRespawnSystemComponent;
469  }
470 
471  //------------------------------------------------------------------------------------------------
472  SCR_GameModeHealthSettings GetGameModeHealthSettings()
473  {
474  return m_pGameModeHealthSettings;
475  }
476 
477  //------------------------------------------------------------------------------------------------
482  SCR_BaseScoringSystemComponent GetScoringSystemComponent()
483  {
484  return m_ScoringSystemComponent;
485  }
486 
487  //------------------------------------------------------------------------------------------------
492  void StartGameMode()
493  {
494  if (!IsMaster())
495  return;
496 
497  if (IsRunning())
498  {
499  Print("Trying to start a gamemode that is already running.", LogLevel.WARNING);
500  return;
501  }
502 
503  m_fTimeElapsed = 0.0;
504  m_eGameState = SCR_EGameModeState.GAME;
505  Replication.BumpMe();
506 
507  // Raise event for authority
508  OnGameStateChanged();
509  }
510 
511  //------------------------------------------------------------------------------------------------
521  protected bool CanStartGameMode()
522  {
523  SCR_BaseGameModeStateComponent pregame = GetStateComponent(SCR_EGameModeState.PREGAME);
524  if (!pregame)
525  return true;
526 
527  return pregame.CanAdvanceState(SCR_EGameModeState.GAME);
528  }
529 
530  //------------------------------------------------------------------------------------------------
538  void EndGameMode(SCR_GameModeEndData endData)
539  {
540  if (!IsMaster())
541  return;
542 
543  // Already over
544  if (!IsRunning())
545  {
546  Print("Trying to end a gamemode that is not running.", LogLevel.WARNING);
547  return;
548  }
549 
550  if (endData == null)
551  endData = SCR_GameModeEndData.CreateSimple();
552 
553  m_pGameEndData = endData;
554  m_eGameState = SCR_EGameModeState.POSTGAME;
555  Replication.BumpMe();
556 
557  // Raise event for authority
558  OnGameStateChanged();
559  }
560 
565  SCR_GameModeEndData GetEndGameData()
566  {
567  if (m_eGameState != SCR_EGameModeState.POSTGAME)
568  return null;
569  else
570  return m_pGameEndData;
571  }
572 
573  ScriptInvoker GetOnGameStart()
574  {
575  return Event_OnGameStart;
576  }
577  ScriptInvoker GetOnGameEnd()
578  {
579  return m_OnGameEnd;
580  }
581  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerAuditSuccess()
582  {
583  return m_OnPlayerAuditSuccess;
584  }
585  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerAuditFail()
586  {
587  return m_OnPlayerAuditFail;
588  }
589  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerAuditTimeouted()
590  {
591  return m_OnPlayerAuditTimeouted;
592  }
593  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerAuditRevived()
594  {
595  return m_OnPlayerAuditRevived;
596  }
597  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerConnected()
598  {
599  return m_OnPlayerConnected;
600  }
601  ScriptInvokerBase<SCR_BaseGameMode_PlayerId> GetOnPlayerRegistered()
602  {
603  return m_OnPlayerRegistered;
604  }
605  ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected> GetOnPlayerDisconnected()
606  {
607  return m_OnPlayerDisconnected;
608  }
613  ScriptInvokerBase<SCR_BaseGameMode_OnPlayerDisconnected> GetOnPostCompPlayerDisconnected()
614  {
615  return m_OnPostCompPlayerDisconnected;
616  }
617  ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity> GetOnPlayerSpawned()
618  {
619  return m_OnPlayerSpawned;
620  }
621  ScriptInvokerBase<SCR_BaseGameMode_OnPlayerKilled> GetOnPlayerKilled()
622  {
623  return m_OnPlayerKilled;
624  }
625  ScriptInvokerBase<SCR_BaseGameMode_PlayerIdAndEntity> GetOnPlayerDeleted()
626  {
627  return m_OnPlayerDeleted;
628  }
629  ScriptInvokerBase<SCR_BaseGameMode_OnPlayerRoleChanged> GetOnPlayerRoleChange()
630  {
631  return m_OnPlayerRoleChange;
632  }
633  ScriptInvoker GetOnWorldPostProcess()
634  {
635  return m_OnWorldPostProcess;
636  }
637  ScriptInvoker GetOnControllableSpawned()
638  {
639  return m_OnControllableSpawned;
640  }
641  ScriptInvoker GetOnControllableDestroyed()
642  {
643  return m_OnControllableDestroyed;
644  }
645  ScriptInvoker GetOnControllableDeleted()
646  {
647  return m_OnControllableDeleted;
648  }
653  ScriptInvoker GetOnGameModeEnd()
654  {
655  return m_OnGameModeEnd;
656  }
657 
658  //------------------------------------------------------------------------------------------------
664  protected void OnGameModeStart()
665  {
666  #ifdef GM_AI_STATS
667  if (IsGameModeStatisticsEnabled())
668  {
669  if (!SCR_GameModeStatistics.IsRecording())
670  SCR_GameModeStatistics.StartRecording();
671  }
672  #endif
673  }
674 
675  //------------------------------------------------------------------------------------------------
682  protected void OnGameModeEnd(SCR_GameModeEndData endData)
683  {
684  ChimeraWorld world = GetGame().GetWorld();
685  if (world)
686  m_GameEndTimeStamp = world.GetLocalTimestamp();
687 
688  m_OnGameModeEnd.Invoke(endData);
689 
690  #ifdef GM_AI_STATS
691  if (IsGameModeStatisticsEnabled())
692  {
693  if (SCR_GameModeStatistics.IsRecording())
694  SCR_GameModeStatistics.StopRecording();
695  }
696  #endif
697 
698  // Automatically restart the session on game mode end if enabled
699  float reloadTime = GetAutoReloadDelay();
700  if (reloadTime > 0)
701  GetGame().GetCallqueue().CallLater(RestartSession, reloadTime * 1000.0, false);
702  }
703 
704  //------------------------------------------------------------------------------------------------
708  WorldTimestamp GetGameEndTimeStamp()
709  {
710  return m_GameEndTimeStamp;
711  }
712 
713  //------------------------------------------------------------------------------------------------
717  float GetAutoReloadDelay()
718  {
719  // Allow the server owner to override it via -autoReload=TIME
720  string autoReloadTimeString;
721  if (System.GetCLIParam("autoreload", autoReloadTimeString))
722  return Math.Clamp(autoReloadTimeString.ToFloat(), 0.0, 600.0);
723 
724  return m_fAutoReloadTime;
725  }
726 
730  protected void RestartSession()
731  {
732  if (!IsMaster())
733  return;
734 
735  Print("SCR_BaseGameMode::RequestScenarioRestart()", LogLevel.DEBUG);
736  if (GameStateTransitions.RequestScenarioRestart())
737  {
738  Print("SCR_BaseGameMode::RequestScenarioRestart() successfull server reload requested!", LogLevel.DEBUG);
739  }
740  }
741 
742  //------------------------------------------------------------------------------------------------
743  protected override void OnGameStart()
744  {
745  BackendApi backendApi = GetGame().GetBackendApi();
746 
747  if (IsMaster())
748  backendApi.NewSession();
749 
750  super.OnGameStart();
751  Event_OnGameStart.Invoke();
752  }
753 
754  //------------------------------------------------------------------------------------------------
755  void OnGameEnd()
756  {
757  m_OnGameEnd.Invoke();
758 
759  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
760  {
761  comp.OnGameEnd();
762  }
763  }
764 
765  //------------------------------------------------------------------------------------------------
766  bool IsFactionChangeAllowed()
767  {
768  return m_bAllowFactionChange;
769  }
770 
771  //------------------------------------------------------------------------------------------------
772  override void OnPlayerAuditSuccess(int iPlayerID)
773  {
774  #ifdef RESPAWN_COMPONENT_VERBOSE
775  Print("SCR_BaseGameMode::OnPlayerAuditSuccess - playerId: " + iPlayerID, LogLevel.DEBUG);
776  #endif
777 
778  super.OnPlayerAuditSuccess(iPlayerID);
779  m_OnPlayerAuditSuccess.Invoke(iPlayerID);
780 
781  // Dispatch event to child components
782  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
783  {
784  comp.OnPlayerAuditSuccess(iPlayerID);
785  }
786  }
787 
788  //------------------------------------------------------------------------------------------------
789  override void OnPlayerAuditFail(int iPlayerID)
790  {
791  #ifdef RESPAWN_COMPONENT_VERBOSE
792  Print("SCR_BaseGameMode::OnPlayerAuditFail - playerId: " + iPlayerID, LogLevel.DEBUG);
793  #endif
794 
795  super.OnPlayerAuditFail(iPlayerID);
796  m_OnPlayerAuditFail.Invoke(iPlayerID);
797 
798  // Dispatch event to child components
799  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
800  {
801  comp.OnPlayerAuditFail(iPlayerID);
802  }
803  }
804 
805  //------------------------------------------------------------------------------------------------
806  override void OnPlayerAuditTimeouted( int iPlayerID)
807  {
808  super.OnPlayerAuditTimeouted(iPlayerID);
809  m_OnPlayerAuditTimeouted.Invoke(iPlayerID);
810 
811  // Dispatch event to child components
812  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
813  {
814  comp.OnPlayerAuditTimeouted(iPlayerID);
815  }
816  };
817 
818  //------------------------------------------------------------------------------------------------
819  override void OnPlayerAuditRevived( int iPlayerID)
820  {
821  super.OnPlayerAuditRevived(iPlayerID);
822  m_OnPlayerAuditRevived.Invoke(iPlayerID);
823 
824  // Dispatch event to child components
825  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
826  {
827  comp.OnPlayerAuditRevived(iPlayerID);
828  }
829  };
830 
831  //------------------------------------------------------------------------------------------------
836  override void OnPlayerConnected(int playerId)
837  {
838  if (!m_bIsHosted)
839  {
840  m_bIsHosted = GetGame().GetPlayerManager().GetPlayerController(playerId).GetRplIdentity() == RplIdentity.Local();
841  Replication.BumpMe();
842  }
843 
844  super.OnPlayerConnected(playerId);
845  m_OnPlayerConnected.Invoke(playerId);
846 
847  // TODO: Please revisit and adjust this, this check results in some nasty branching and possible oversights/errors
848  // Wait for backend response if dedicated server is used and is not run without backend functionality
849  if (m_pRespawnSystemComponent && (RplSession.Mode() != RplMode.Dedicated || System.IsCLIParam("nobackend")))
850  {
851  #ifdef RESPAWN_COMPONENT_VERBOSE
852  Print("SCR_BaseGameMode::OnPlayerConnected - playerId: " + playerId, LogLevel.DEBUG);
853  #endif
854  }
855 
856  // Dispatch event to child components
857  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
858  {
859  comp.OnPlayerConnected(playerId);
860  }
861 
862  // DON'T! Leave that up to game mode respawning
863  // SetPlayerRandomLoadout(playerId);
864 
865  #ifdef TREE_DESTRUCTION
866  int count = SCR_DestructibleTree.DestructibleTrees.Count();
867  for (int i = 0; i < count; i++)
868  {
869  SCR_DestructibleTree.DestructibleTrees[i].OnPlayerConnected();
870  }
871  #endif
872  }
873 
874  //------------------------------------------------------------------------------------------------
879  protected override void OnPlayerDisconnected(int playerId, KickCauseCode cause, int timeout)
880  {
881  super.OnPlayerDisconnected(playerId, cause, timeout);
882  m_OnPlayerDisconnected.Invoke(playerId, cause, timeout);
883 
884  // RespawnSystemComponent is not a SCR_BaseGameModeComponent, so for now we have to
885  // propagate these events manually.
886  if (IsMaster())
887  m_pRespawnSystemComponent.OnPlayerDisconnected_S(playerId, cause, timeout);
888 
889  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
890  {
891  comp.OnPlayerDisconnected(playerId, cause, timeout);
892  }
893 
894  m_OnPostCompPlayerDisconnected.Invoke(playerId, cause, timeout);
895 
896  if (IsMaster())
897  {
898  IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerId);
899  if (controlledEntity)
900  {
901  if (SCR_ReconnectComponent.GetInstance() && SCR_ReconnectComponent.GetInstance().IsReconnectEnabled())
902  {
903  if (SCR_ReconnectComponent.GetInstance().OnPlayerDC(playerId, cause)) // if conditions to allow reconnect pass, skip the entity delete
904  {
905  CharacterControllerComponent charController = CharacterControllerComponent.Cast(controlledEntity.FindComponent(CharacterControllerComponent));
906  if (charController)
907  {
908  charController.SetMovement(0, vector.Forward);
909  }
910 
911  CompartmentAccessComponent compAccess = CompartmentAccessComponent.Cast(controlledEntity.FindComponent(CompartmentAccessComponent)); // TODO nullcheck
912  if (compAccess)
913  {
914  BaseCompartmentSlot compartment = compAccess.GetCompartment();
915  if (compartment)
916  {
918  {
919  CarControllerComponent carController = CarControllerComponent.Cast(compartment.GetVehicle().FindComponent(CarControllerComponent));
920  if (carController)
921  {
922  carController.Shutdown();
923  carController.StopEngine(false);
924  }
925  }
926  else
927  {
928  CarControllerComponent_SA carController = CarControllerComponent_SA.Cast(compartment.GetVehicle().FindComponent(CarControllerComponent_SA));
929  if (carController)
930  {
931  carController.Shutdown();
932  carController.StopEngine(false);
933  }
934  }
935  }
936  }
937 
938  return;
939  }
940  }
941 
942  RplComponent.DeleteRplEntity(controlledEntity, false);
943  }
944  }
945  }
946 
947  //------------------------------------------------------------------------------------------------
952  protected override void OnPlayerRegistered(int playerId)
953  {
954  super.OnPlayerRegistered(playerId);
955  m_OnPlayerRegistered.Invoke(playerId);
956 
957  // RespawnSystemComponent is not a SCR_BaseGameModeComponent, so for now we have to
958  // propagate these events manually.
959  if (IsMaster())
960  m_pRespawnSystemComponent.OnPlayerRegistered_S(playerId);
961 
962  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
963  {
964  comp.OnPlayerRegistered(playerId);
965  }
966 
967  #ifdef GMSTATS
968  if (IsGameModeStatisticsEnabled())
969  SCR_GameModeStatistics.RecordConnection(playerId, GetGame().GetPlayerManager().GetPlayerName(playerId));
970  #endif
971  }
972 
973  //------------------------------------------------------------------------------------------------
979  [Obsolete("Use SCR_BaseGameMode.OnPlayerSpawnFinalize_S")]
980  protected override void OnPlayerSpawned(int playerId, IEntity controlledEntity)
981  {
982  super.OnPlayerSpawned(playerId, controlledEntity);
983  m_OnPlayerSpawned.Invoke(playerId, controlledEntity);
984 
985  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
986  {
987  comp.OnPlayerSpawned(playerId, controlledEntity);
988  }
989 
990  #ifdef GMSTATS
991  if (IsGameModeStatisticsEnabled())
992  {
993  FactionAffiliationComponent fac = FactionAffiliationComponent.Cast(controlledEntity.FindComponent(FactionAffiliationComponent));
994  SCR_GameModeStatistics.RecordSpawn(playerId, fac.GetAffiliatedFaction().GetFactionColor().PackToInt());
995  }
996  #endif
997  }
998 
999  //------------------------------------------------------------------------------------------------
1000  protected override bool HandlePlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
1001  {
1002  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1003  {
1004  // First component that returns false overrides the behaviour and can handle
1005  // the kill based on their respective needs
1006  if (!comp.HandlePlayerKilled(playerId, playerEntity, killerEntity, killer))
1007  {
1008  OnPlayerKilledHandled(playerId, playerEntity, killerEntity, killer);
1009  return false;
1010  }
1011  }
1012 
1013  // Handle automatically
1014  return true;
1015  }
1016 
1017  //------------------------------------------------------------------------------------------------
1019  protected override void OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
1020  {
1021  super.OnPlayerKilled(playerId, playerEntity, killerEntity, killer);
1022 
1023  m_OnPlayerKilled.Invoke(playerId, playerEntity, killerEntity, killer);
1024 
1025  // RespawnSystemComponent is not a SCR_BaseGameModeComponent, so for now we have to
1026  // propagate these events manually.
1027  if (IsMaster())
1028  m_pRespawnSystemComponent.OnPlayerKilled_S(playerId, playerEntity, killerEntity, killer);
1029 
1030  // Dispatch events to children components
1031  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1032  {
1033  comp.OnPlayerKilled(playerId, playerEntity, killerEntity, killer);
1034  }
1035 
1036  #ifdef GMSTATS
1037  if (IsGameModeStatisticsEnabled())
1038  SCR_GameModeStatistics.RecordDeath(playerId, playerEntity, killerEntity, killer);
1039  #endif
1040  }
1041 
1042  //------------------------------------------------------------------------------------------------
1044  protected void OnPlayerKilledHandled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
1045  {
1046  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1047  comp.OnPlayerKilledHandled(playerId, playerEntity, killerEntity, killer);
1048  }
1049 
1050  //------------------------------------------------------------------------------------------------
1051  protected /*override*/ void OnPlayerDeleted(int playerId, IEntity player)
1052  {
1053  // RespawnSystemComponent is not a SCR_BaseGameModeComponent, so for now we have to
1054  // propagate these events manually.
1055  if (IsMaster())
1056  m_pRespawnSystemComponent.OnPlayerDeleted_S(playerId);
1057 
1058  //super.OnPlayerDeleted(playerId, player);
1059  m_OnPlayerDeleted.Invoke(playerId, player);
1060 
1061  // Dispatch events to children components
1062  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1063  {
1064  comp.OnPlayerDeleted(playerId, player);
1065  }
1066  }
1067 
1068  //------------------------------------------------------------------------------------------------
1074  protected override void OnPlayerRoleChange(int playerId, EPlayerRole roleFlags)
1075  {
1076  super.OnPlayerRoleChange(playerId, roleFlags);
1077  m_OnPlayerRoleChange.Invoke(playerId, roleFlags);
1078 
1079  // Dispatch events to children components
1080  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1081  {
1082  comp.OnPlayerRoleChange(playerId, roleFlags);
1083  }
1084  }
1085 
1086  //------------------------------------------------------------------------------------------------
1091  override event void OnWorldPostProcess(World world)
1092  {
1093  super.OnWorldPostProcess(world);
1094  m_OnWorldPostProcess.Invoke(world);
1095 
1096  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1097  {
1098  comp.OnWorldPostProcess(world);
1099  }
1100  };
1101 
1102  //------------------------------------------------------------------------------------------------
1103  /*
1104  When a controllable entity is spawned, this event is raised.
1105  \param entity Spawned entity that raised this event
1106  */
1107  protected override void OnControllableSpawned(IEntity entity)
1108  {
1109  super.OnControllableSpawned(entity);
1110  m_OnControllableSpawned.Invoke(entity);
1111 
1112  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1113  {
1114  comp.OnControllableSpawned(entity);
1115  }
1116  }
1117 
1118  //------------------------------------------------------------------------------------------------
1119  /*
1120  When a controllable entity is destroyed, this event is raised.
1121  \param entity Destroyed entity that raised this event
1122  \param killerEntity Entity that killed the entity (can be null)
1123  \param killer Instigator entity that destroyed our victim
1124  */
1125  protected override void OnControllableDestroyed(IEntity entity, IEntity killerEntity, notnull Instigator instigator)
1126  {
1127  super.OnControllableDestroyed(entity, killerEntity, instigator);
1128  m_OnControllableDestroyed.Invoke(entity, killerEntity, instigator);
1129 
1130  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1131  {
1132  comp.OnControllableDestroyed(entity, killerEntity, instigator);
1133  }
1134  }
1135 
1136  //------------------------------------------------------------------------------------------------
1137  /*
1138  Prior to a controllable entity being DELETED, this event is raised.
1139  Controllable entity is such that has BaseControllerComponent and can be
1140  possessed either by a player, an AI or stay unpossessed.
1141  \param entity Entity about to be deleted
1142  */
1143  protected override void OnControllableDeleted(IEntity entity)
1144  {
1145  super.OnControllableDeleted(entity);
1146  m_OnControllableDeleted.Invoke(entity);
1147 
1148  foreach (SCR_BaseGameModeComponent comp : m_aAdditionalGamemodeComponents)
1149  {
1150  comp.OnControllableDeleted(entity);
1151  }
1152 
1153  // Ensure that controlled entity is a player
1154  int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(entity);
1155  if (playerId > 0)
1156  OnPlayerDeleted(playerId, entity);
1157  }
1158 
1159 
1160  //------------------------------------------------------------------------------------------------
1168  void OnSpawnPlayerEntityFailure_S(SCR_SpawnRequestComponent requestComponent, SCR_SpawnHandlerComponent handlerComponent, IEntity entity, SCR_SpawnData data, SCR_ESpawnResult reason)
1169  {
1170  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
1171  component.OnSpawnPlayerEntityFailure_S(requestComponent, handlerComponent, entity, data, reason);
1172  }
1173 
1174  //------------------------------------------------------------------------------------------------
1179  void OnPlayerEntityChanged_S(int playerId, IEntity previousEntity, IEntity newEntity)
1180  {
1181  }
1182 
1196  bool PreparePlayerEntity_S(SCR_SpawnRequestComponent requestComponent, SCR_SpawnHandlerComponent handlerComponent, SCR_SpawnData data, IEntity entity)
1197  {
1198  // Example(s):
1199  // - load some data from storage, fill inventory with stored items
1200  // - apply loaded data by setting provided entity to bleed for a certain amount
1201  // - drop character unconscious?
1202 
1203  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
1204  {
1205  if (!component.PreparePlayerEntity_S(requestComponent, handlerComponent, data, entity))
1206  return false;
1207  }
1208 
1209  // Entity preparation has succeeded
1210  return true;
1211  }
1212 
1213  //------------------------------------------------------------------------------------------------
1224  void OnPlayerSpawnFinalize_S(SCR_SpawnRequestComponent requestComponent, SCR_SpawnHandlerComponent handlerComponent, SCR_SpawnData data, IEntity entity)
1225  {
1226  SCR_SpawnPointSpawnData spawnPointData = SCR_SpawnPointSpawnData.Cast(data);
1227  if (spawnPointData)
1228  {
1229  OnPlayerSpawnOnPoint_S(requestComponent, handlerComponent, entity, spawnPointData);
1230  }
1231 
1232  foreach (SCR_BaseGameModeComponent component : m_aAdditionalGamemodeComponents)
1233  component.OnPlayerSpawnFinalize_S(requestComponent, handlerComponent, data, entity);
1234 
1235  SCR_PlayerLoadoutComponent loadoutComp = SCR_PlayerLoadoutComponent.Cast(requestComponent.GetPlayerController().FindComponent(SCR_PlayerLoadoutComponent));
1236  if (!SCR_PossessSpawnData.Cast(data) // hotfix when player is spawned through game master, their loadout would change to the saved loadout
1237  && loadoutComp && loadoutComp.GetLoadout())
1238  loadoutComp.GetLoadout().OnLoadoutSpawned(GenericEntity.Cast(entity), requestComponent.GetPlayerId());
1239 
1240  m_OnPlayerSpawned.Invoke(requestComponent.GetPlayerId(), entity);
1241  }
1242 
1243  //------------------------------------------------------------------------------------------------
1249  void OnPlayerSpawnOnPoint_S(SCR_SpawnRequestComponent requestComponent, SCR_SpawnHandlerComponent handlerComponent, IEntity entity, SCR_SpawnPointSpawnData spawnPointData)
1250  {
1251  }
1252 
1253  //------------------------------------------------------------------------------------------------
1258  void OnPlayerLoadoutSet_S(SCR_PlayerLoadoutComponent loadoutComponent, SCR_BasePlayerLoadout loadout)
1259  {
1260  }
1261 
1262  //------------------------------------------------------------------------------------------------
1267  void OnPlayerFactionSet_S(SCR_PlayerFactionAffiliationComponent factionComponent, Faction faction)
1268  {
1269  }
1270 
1271  //------------------------------------------------------------------------------------------------
1281  bool CanPlayerSpawn_S(SCR_SpawnRequestComponent requestComponent, SCR_SpawnHandlerComponent handlerComponent, SCR_SpawnData data, out SCR_ESpawnResult result = SCR_ESpawnResult.SPAWN_NOT_ALLOWED)
1282  {
1283  if (m_RespawnTimerComponent)
1284  {
1285  int playerId = requestComponent.GetPlayerId();
1286 
1287  // If player has not been enqueued yet, ignore the spawn timer
1288  if (m_RespawnTimerComponent.IsPlayerEnqueued(playerId))
1289  {
1290  float spawnPointTime = 0;
1291  if (data.IsInherited(SCR_SpawnPointSpawnData))
1292  {
1294  spawnPointTime = spData.GetSpawnPoint().GetRespawnTime();
1295  }
1296 
1297  if (!m_RespawnTimerComponent.GetCanPlayerSpawn(playerId, spawnPointTime))
1298  {
1299  result = SCR_ESpawnResult.NOT_ALLOWED_TIMER;
1300  return false;
1301  }
1302  }
1303  }
1304 
1305  result = SCR_ESpawnResult.OK;
1306  return true;
1307  }
1308 
1309  //------------------------------------------------------------------------------------------------
1311  int GetPlayerRemainingRespawnTime(int playerID)
1312  {
1313  // Respawn timers
1314  if (m_RespawnTimerComponent)
1315  return m_RespawnTimerComponent.GetPlayerRemainingTime(playerID);
1316 
1317  return 0;
1318  }
1319 
1320  //------------------------------------------------------------------------------------------------
1321  override bool RplSave(ScriptBitWriter writer)
1322  {
1323  EGameFlags gameFlags = GetGame().GetGameFlags();
1324  writer.WriteIntRange(gameFlags, 0, (EGameFlags.Last<<1)-1);
1325 
1326  return true;
1327  }
1328 
1329  //------------------------------------------------------------------------------------------------
1330  override bool RplLoad(ScriptBitReader reader)
1331  {
1332  EGameFlags gameFlags;
1333  reader.ReadIntRange(gameFlags, 0, (EGameFlags.Last<<1)-1);
1334 
1335  GetGame().SetGameFlags(gameFlags, true);
1336 
1337  return true;
1338  }
1339 
1340  #ifdef GAME_MODE_DEBUG
1341 
1342  //------------------------------------------------------------------------------------------------
1344  void Diag_DrawPlayersWindow()
1345  {
1346  //DbgUI.Begin("SCR_BaseGameMode: Players Diag");
1347  array<int> connectedPlayers = {};
1348  GetGame().GetPlayerManager().GetPlayers(connectedPlayers);
1349 
1350  array<int> disconnectedPlayers = {};
1351  GetGame().GetPlayerManager().GetDisconnectedPlayers(disconnectedPlayers);
1352 
1353  DbgUI.Begin("SCR_BaseGameMode: Connected players");
1354  {
1355  for (int i = 0, cnt = connectedPlayers.Count(); i < cnt; i++)
1356  {
1357  int playerId = connectedPlayers[i];
1358  Diag_DrawPlayerInfo(playerId);
1359  }
1360  }
1361  DbgUI.End();
1362  DbgUI.Begin("SCR_BaseGameMode: Disconnected players");
1363  {
1364  for (int i = 0, cnt = disconnectedPlayers.Count(); i < cnt; i++)
1365  {
1366  int playerId = disconnectedPlayers[i];
1367  Diag_DrawPlayerInfo(playerId);
1368  }
1369  }
1370  DbgUI.End();
1371  }
1372 
1373  //------------------------------------------------------------------------------------------------
1376  void Diag_DrawPlayerInfo(int playerId)
1377  {
1378  string tmp = string.Format("Player %1: (name: %2)", playerId, GetGame().GetPlayerManager().GetPlayerName(playerId));
1379  array<string> extra = {};
1380 
1381  // Fetch faction info (if present)
1382  SCR_FactionManager factionManager = SCR_FactionManager.Cast(GetGame().GetFactionManager());
1383  if (factionManager)
1384  {
1385  string factionKey = "None";
1386  Faction faction = factionManager.GetPlayerFaction(playerId);
1387  if (faction)
1388  {
1389  factionKey = faction.GetFactionKey();
1390  }
1391 
1392  extra.Insert(string.Format("Faction: %1", factionKey));
1393  }
1394 
1395  // Fetch loadout info (if present)
1397  if (loadoutManager)
1398  {
1399  string loadoutKey = "None";
1400  SCR_BasePlayerLoadout loadout = loadoutManager.GetPlayerLoadout(playerId);
1401  if (loadout)
1402  {
1403  loadoutKey = loadout.GetLoadoutName();
1404  }
1405 
1406  extra.Insert(string.Format("Loadout: %1", loadoutKey));
1407  }
1408 
1409  // If any additional info is present, start formatting
1410  if (!extra.IsEmpty())
1411  {
1412  const string separator = "\n ";
1413  for (int i = 0, count = extra.Count(); i < count; i++)
1414  {
1415  tmp += string.Format("%1%2", separator, extra[i] );
1416  }
1417  }
1418 
1419  DbgUI.Text(tmp);
1420  }
1421 
1422  //------------------------------------------------------------------------------------------------
1424  void Diag_DrawControlledEntitiesWindow()
1425  {
1426  array<int> allPlayers = {};
1427  GetGame().GetPlayerManager().GetAllPlayers(allPlayers);
1428 
1429  DbgUI.Begin("SCR_BaseGameMode: Controlled Entities");
1430  {
1431  for (int i = 0, cnt = allPlayers.Count(); i < cnt; i++)
1432  {
1433  int playerId = allPlayers[i];
1434  Diag_DrawControlledEntityInfo(playerId);
1435  }
1436  }
1437  DbgUI.End();
1438  }
1439 
1440  //------------------------------------------------------------------------------------------------
1443  void Diag_DrawControlledEntityInfo(int playerId)
1444  {
1445  string tmp = string.Format("Player %1: (name: %2)", playerId, GetGame().GetPlayerManager().GetPlayerName(playerId));
1446  array<string> extra = {};
1447 
1448  // IsConnected?
1449  if (GetGame().GetPlayerManager().IsPlayerConnected(playerId))
1450  {
1451  extra.Insert("IsConnected: True");
1452  }
1453  else
1454  extra.Insert("IsConnected: False");
1455 
1456  // Controlled entity
1457  IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerId);
1458  if (controlledEntity)
1459  {
1460  extra.Insert(string.Format("Entity: %1", controlledEntity));
1461 
1462  RplComponent rplComponent = RplComponent.Cast(controlledEntity.FindComponent(RplComponent));
1463  if (rplComponent)
1464  {
1465  extra.Insert(string.Format("RplId: %1", rplComponent.Id()));
1466  }
1467  }
1468  else
1469  {
1470  extra.Insert("Entity: None");
1471  }
1472 
1473 
1474  // If any additional info is present, start formatting
1475  if (!extra.IsEmpty())
1476  {
1477  const string separator = "\n ";
1478  for (int i = 0, count = extra.Count(); i < count; i++)
1479  {
1480  tmp += string.Format("%1%2", separator, extra[i] );
1481  }
1482  }
1483 
1484  DbgUI.Text(tmp);
1485  }
1486 
1487  //------------------------------------------------------------------------------------------------
1489  void Diag_DrawComponentsWindow()
1490  {
1491  DbgUI.Begin("SCR_BaseGameMode: Components");
1492  {
1493  int numComponents = m_aAdditionalGamemodeComponents.Count();
1494  DbgUI.Text(string.Format("NumComponents: %1", numComponents));
1495 
1496  for (int i = 0; i < numComponents; i++)
1497  {
1498  Diag_DrawComponentInfo(i, m_aAdditionalGamemodeComponents[i]);
1499  }
1500  }
1501  DbgUI.End();
1502  }
1503 
1504  //------------------------------------------------------------------------------------------------
1506  void Diag_DrawComponentInfo(int index, SCR_BaseGameModeComponent component)
1507  {
1508  DbgUI.Text(string.Format("%1: %2", index, component));
1509  }
1510 
1511  //------------------------------------------------------------------------------------------------
1513  void Diag_DrawGameModeWindow()
1514  {
1515  DbgUI.Begin("SCR_BaseGameMode");
1516  {
1517  string elapsedTime = string.Format("Elapsed time: %1 s", GetElapsedTime());
1518  DbgUI.Text(elapsedTime);
1519 
1520  string running = string.Format("IsRunning: %1", IsRunning());
1521  DbgUI.Text(running);
1522 
1523  string state = string.Format("State: %1", SCR_Enum.GetEnumName(SCR_EGameModeState, GetState()));
1524  DbgUI.Text(state);
1525 
1526  string flags = string.Format("TestFlags: %1 (%2)", SCR_Enum.FlagsToString(EGameFlags, m_eGameState), m_eGameState);
1527  DbgUI.Text(flags);
1528 
1529  if (IsMaster())
1530  {
1531  DbgUI.Spacer(16);
1532  DbgUI.Text("Authority details:");
1533 
1534  float autoReloadDelay = GetAutoReloadDelay();
1535  if (autoReloadDelay > 0)
1536  {
1537  DbgUI.Text(string.Format("Auto reload: %1 seconds.", autoReloadDelay));
1538  }
1539  else
1540  {
1541  DbgUI.Text("Auto reload: Disabled.");
1542  }
1543 
1544  DbgUI.Spacer(16);
1545 
1546  if (DbgUI.Button("End Session"))
1547  EndGameMode(SCR_GameModeEndData.CreateSimple(EGameOverTypes.FACTION_DRAW));
1548 
1549  if (DbgUI.Button("Restart Session"))
1550  RestartSession();
1551  }
1552  }
1553  DbgUI.End();
1554  }
1555  #endif
1556 
1557  //------------------------------------------------------------------------------------------------
1559  void HandleOnTasksInitialized();
1560 
1561  //------------------------------------------------------------------------------------------------
1564  protected void SetLocalControls(bool enabled)
1565  {
1566  PlayerController playerController = GetGame().GetPlayerController();
1567  if (playerController)
1568  {
1569  IEntity controlledEntity = playerController.GetControlledEntity();
1570  if (controlledEntity)
1571  {
1572  ChimeraCharacter character = ChimeraCharacter.Cast(controlledEntity);
1573  if (character)
1574  {
1575  CharacterControllerComponent controller = character.GetCharacterController();
1576  if (controller)
1577  {
1578  bool doDisable = !enabled;
1579  controller.SetDisableWeaponControls(doDisable);
1580  controller.SetDisableMovementControls(doDisable);
1581  }
1582  }
1583  }
1584  }
1585  }
1586 
1587  #ifdef GM_AI_STATS
1588  private float m_fLastRecordTime;
1589 
1590  private float m_fLastFlushTime;
1591  private float m_fFlushRecordInterval = 10000; // 10s
1592 
1593  //------------------------------------------------------------------------------------------------
1594  private void UpdateStatistics(IEntity owner)
1595  {
1596  // Create new records only ever so often
1597  float timeStamp = owner.GetWorld().GetWorldTime();
1598  if (timeStamp > m_fLastRecordTime + SCR_GameModeStatistics.RECORD_INTERVAL_MS)
1599  {
1600  m_fLastRecordTime = timeStamp;
1601 
1602  #ifdef GMSTATS
1603  PlayerManager pm = GetGame().GetPlayerManager();
1604  array<int> players = {};
1605  pm.GetPlayers(players);
1606 
1607  foreach (int pid : players)
1608  {
1609  IEntity ctrlEnt = pm.GetPlayerControlledEntity(pid);
1610  if (!ctrlEnt)
1611  continue;
1612 
1613  SCR_GameModeStatistics.RecordMovement(ctrlEnt, pid);
1614  }
1615  #endif
1616  #ifdef AISTATS
1617  auto aiWorld = SCR_AIWorld.Cast(GetGame().GetAIWorld());
1618  if (aiWorld)
1619  {
1620  array<AIAgent> aiAgents = {};
1621  aiWorld.GetAIAgents(aiAgents);
1622  foreach (AIAgent agent : aiAgents)
1623  {
1624  SCR_GameModeStatistics.RecordAILOD(agent);
1625  }
1626  }
1627  #endif
1628  }
1629 
1630  // Flush data if recording in smaller intervals
1631  if (timeStamp > m_fLastFlushTime + m_fFlushRecordInterval)
1632  {
1633  m_fLastFlushTime = timeStamp;
1634  if (IsGameModeStatisticsEnabled())
1635  {
1636  if (SCR_GameModeStatistics.IsRecording())
1637  SCR_GameModeStatistics.Flush();
1638  }
1639  }
1640  }
1641  #endif
1642 
1643  //------------------------------------------------------------------------------------------------
1646  bool GetAllowControls()
1647  {
1648  return m_bAllowControls;
1649  }
1650 
1651  //------------------------------------------------------------------------------------------------
1654  protected bool GetAllowControlsTarget()
1655  {
1656  SCR_BaseGameModeStateComponent stateComponent = GetStateComponent(GetState());
1657  if (stateComponent)
1658  return stateComponent.GetAllowControls();
1659 
1660  return true;
1661  }
1662 
1663  //------------------------------------------------------------------------------------------------
1665  SCR_BaseGameModeStateComponent GetStateComponent(SCR_EGameModeState state)
1666  {
1667  SCR_BaseGameModeStateComponent stateComponent;
1668  if (m_mStateComponents.Find(state, stateComponent))
1669  return stateComponent;
1670 
1671  return null;
1672  }
1673 
1674  //------------------------------------------------------------------------------------------------
1675  // TODO@AS: Small thing, but get rid of m_fTimeElapsed and use
1676  // some sort of m_fStartTime and Replication.Time() instead!
1677  override void EOnFrame(IEntity owner, float timeSlice)
1678  {
1679  #ifdef GM_AI_STATS
1680  if (IsGameModeStatisticsEnabled())
1681  UpdateStatistics(owner);
1682  #endif
1683 
1684  if (m_bUseSpawnPreload && m_SpawnPreload)
1685  HandleSpawnPreload(timeSlice);
1686 
1687  // Allow to accumulate time in pre-game too.
1688  SCR_BaseGameModeStateComponent pregameComponent = GetStateComponent(SCR_EGameModeState.PREGAME);
1689  bool isPregame = GetState() == SCR_EGameModeState.PREGAME;
1690  // Increment elapsed time on every machine
1691  bool isRunning = IsRunning();
1692  if (isRunning || isPregame)
1693  {
1694  bool canAdvanceTime = true;
1695 
1696  // Check if any players are present; if using "advance time requires players"
1697  // we will only advance the time if at least one player is present;
1698  // this is fairly easy to do, because dedicated (headless) server does not
1699  // count as a player in the PlayerManager
1700  if (m_bAdvanceTimeRequiresPlayers)
1701  {
1702  int playerCount = GetGame().GetPlayerManager().GetPlayerCount();
1703  if (playerCount == 0)
1704  canAdvanceTime = false;
1705  }
1706 
1707  if (canAdvanceTime)
1708  m_fTimeElapsed += timeSlice;
1709  }
1710 
1711  // As the authority make corrections as needed
1712  if (IsMaster())
1713  {
1714  if (m_fTimeElapsed >= m_fLastTimeCorrection + m_fTimeCorrectionInterval)
1715  {
1716  Replication.BumpMe();
1717  m_fLastTimeCorrection = m_fTimeElapsed;
1718  }
1719 
1720  // Transition from pre-game to game if possible
1721  // Either fully automatic transition (no component)
1722  // or state-driven transition based on component logic
1723  if (isPregame && (!pregameComponent || pregameComponent.CanAdvanceState(SCR_EGameModeState.GAME)))
1724  {
1725  if (CanStartGameMode())
1726  StartGameMode();
1727  }
1728  else
1729  {
1730  // Time limit end game transition to post-game if possible
1731  if (IsRunning())
1732  {
1733  SCR_BaseGameModeStateComponent gameState = GetStateComponent(SCR_EGameModeState.GAME);
1734  if (gameState && gameState.CanAdvanceState(SCR_EGameModeState.POSTGAME))
1735  {
1736  // Clamp time to maximum
1737  m_fTimeElapsed = Math.Clamp(m_fTimeElapsed, 0, gameState.GetDuration());
1738 
1739  // Terminate session
1740  SCR_GameModeEndData data = SCR_GameModeEndData.CreateSimple(EGameOverTypes.EDITOR_FACTION_DRAW); // TODO: Once FACTION_DRAW or TIME_LIMIT works..
1741  EndGameMode(data);
1742  }
1743  }
1744  }
1745 
1746  // Update controls state
1747  bool shouldAllowControls = GetAllowControlsTarget();
1748  if (shouldAllowControls != m_bAllowControls)
1749  {
1750  m_bAllowControls = shouldAllowControls;
1751  Replication.BumpMe();
1752  }
1753  }
1754 
1755 
1756  // Should we disable local player controls?
1757  bool allowControls = GetAllowControls();
1758  SetLocalControls(allowControls);
1759 
1760  #ifdef GAME_MODE_DEBUG
1761  if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_GAME_MODE))
1762  {
1763  Diag_DrawGameModeWindow();
1764  Diag_DrawComponentsWindow();
1765  Diag_DrawPlayersWindow();
1766  Diag_DrawControlledEntitiesWindow();
1767  }
1768  #endif
1769  }
1770 
1771  //------------------------------------------------------------------------------------------------
1772  override void EOnInit(IEntity owner)
1773  {
1774  // Set Test Game Flags
1775  #ifdef WORKBENCH
1776  if (GetGame().GetWorldEntity() && !GetGame().AreGameFlagsObtained())
1777  {
1778  GetGame().SetGameFlags(m_eTestGameFlags, false);
1779  }
1780  #endif
1781 
1782  //~ Remove any duplicate entries
1783  if (m_aDisabledResourceTypes.IsEmpty())
1784  {
1785  //~ TODO: Make this cleaner
1786 
1787  set<EResourceType> duplicateRemoveSet = new set<EResourceType>();
1788 
1789  foreach (EResourceType resourceType : m_aDisabledResourceTypes)
1790  {
1791  duplicateRemoveSet.Insert(resourceType);
1792  }
1793 
1794  m_aDisabledResourceTypes.Clear();
1795  foreach (EResourceType resourceType : duplicateRemoveSet)
1796  {
1797  m_aDisabledResourceTypes.Insert(resourceType);
1798  }
1799  }
1800 
1801  // Find required components
1802  m_RplComponent = RplComponent.Cast(owner.FindComponent(RplComponent));
1803  m_pRespawnSystemComponent = SCR_RespawnSystemComponent.Cast(owner.FindComponent(SCR_RespawnSystemComponent));
1804  m_RespawnTimerComponent = SCR_RespawnTimerComponent.Cast(owner.FindComponent(SCR_RespawnTimerComponent));
1805  m_ScoringSystemComponent = SCR_BaseScoringSystemComponent.Cast(owner.FindComponent(SCR_BaseScoringSystemComponent));
1806  m_pGameModeHealthSettings = SCR_GameModeHealthSettings.Cast(owner.FindComponent(SCR_GameModeHealthSettings));
1807 
1808  if (!m_RplComponent)
1809  Print("SCR_BaseGameMode is missing RplComponent!", LogLevel.ERROR);
1810  if (!m_pRespawnSystemComponent)
1811  Print("SCR_BaseGameMode is missing SCR_RespawnSystemComponent!", LogLevel.WARNING);
1812 
1813  if (!m_aAdditionalGamemodeComponents)
1814  m_aAdditionalGamemodeComponents = new array<SCR_BaseGameModeComponent>();
1815 
1816  array<Managed> additionalComponents = new array<Managed>();
1817  int count = owner.FindComponents(SCR_BaseGameModeComponent, additionalComponents);
1818 
1819  m_aAdditionalGamemodeComponents.Clear();
1820  for (int i = 0; i < count; i++)
1821  {
1822  SCR_BaseGameModeComponent comp = SCR_BaseGameModeComponent.Cast(additionalComponents[i]);
1823  m_aAdditionalGamemodeComponents.Insert(comp);
1824  }
1825 
1826  // Find and sort state components
1827  array<Managed> stateComponents = new array<Managed>();
1828  int stateCount = owner.FindComponents(SCR_BaseGameModeStateComponent, stateComponents);
1829  for (int i = 0; i < stateCount; i++)
1830  {
1831  SCR_BaseGameModeStateComponent stateComponent = SCR_BaseGameModeStateComponent.Cast(stateComponents[i]);
1832  SCR_EGameModeState state = stateComponent.GetAffiliatedState();
1833  // Invalid state
1834  if (state < 0)
1835  {
1836  Print("Skipping one of SCR_BaseGameStateComponent(s), invalid affiliated state!", LogLevel.ERROR);
1837  continue;
1838  }
1839 
1840  if (m_mStateComponents.Contains(state))
1841  {
1842  string stateName = SCR_Enum.GetEnumName(SCR_EGameModeState, state);
1843  Print("Skipping one of SCR_BaseGameStateComponent(s), duplicate component for state: " + stateName + "!", LogLevel.ERROR);
1844  continue;
1845  }
1846 
1847  m_mStateComponents.Insert(state, stateComponent);
1848  }
1849  }
1850 
1851  /*
1852  Preload handling
1853  */
1854 
1855  //------------------------------------------------------------------------------------------------
1856  OnPreloadFinishedInvoker GetOnPreloadFinished()
1857  {
1858  if (!m_OnPreloadFinished)
1859  m_OnPreloadFinished = new OnPreloadFinishedInvoker();
1860 
1861  return m_OnPreloadFinished;
1862  }
1863 
1864  //------------------------------------------------------------------------------------------------
1867  void StartSpawnPreload(vector position)
1868  {
1869  m_SpawnPreload = SCR_SpawnPreload.PreloadSpawnPosition(position);
1870  if (!m_SpawnPreload && m_OnPreloadFinished)
1871  m_OnPreloadFinished.Invoke();
1872 
1873  }
1874 
1875  //------------------------------------------------------------------------------------------------
1876  protected void HandleSpawnPreload(float timeSlice)
1877  {
1878  bool finished = m_SpawnPreload.Update(timeSlice);
1879  if (finished)
1880  {
1881  m_SpawnPreload = null;
1882  if (m_OnPreloadFinished)
1883  m_OnPreloadFinished.Invoke();
1884  }
1885  }
1886 
1887  //------------------------------------------------------------------------------------------------
1888  // constructor
1889  void SCR_BaseGameMode(IEntitySource src, IEntity parent)
1890  {
1891  #ifdef GAME_MODE_DEBUG
1892  if (!s_DebugRegistered)
1893  {
1894  DiagMenu.RegisterMenu(SCR_DebugMenuID.DEBUGUI_GAME_MODE_MENU, "GameMode", "");
1895  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_GAME_MODE, "", "Game Mode", "GameMode");
1896  s_DebugRegistered = true;
1897  }
1898  #endif
1899 
1900  Activate();
1901  SetEventMask(EntityEvent.INIT | EntityEvent.FRAME);
1902  }
1903 
1904  //------------------------------------------------------------------------------------------------
1905  // destructor
1906  void ~SCR_BaseGameMode()
1907  {
1908  #ifdef GAME_MODE_DEBUG
1909  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_GAME_MODE);
1910  s_DebugRegistered = false;
1911  #endif
1912 
1913  #ifdef GM_AI_STATS
1914  if (SCR_GameModeStatistics.IsRecording())
1915  SCR_GameModeStatistics.StopRecording();
1916  #endif
1917  }
1918 
1919  #ifdef GM_AI_STATS
1920  //------------------------------------------------------------------------------------------------
1922  private bool IsGameModeStatisticsEnabled()
1923  {
1924  // not authority
1925  if (m_RplComponent && !m_RplComponent.IsMaster())
1926  return false;
1927 
1928  return GetGame().InPlayMode();
1929  }
1930  #endif
1931 }
SCR_PlayerLoadoutComponent
Definition: SCR_PlayerLoadoutComponent.c:16
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
AreGameFlagsObtained
bool AreGameFlagsObtained()
Definition: game.c:558
SCR_Enum
Definition: SCR_Enum.c:1
SCR_ESpawnResult
SCR_ESpawnResult
Definition: SCR_ESpawnResult.c:8
EPlayerRole
EPlayerRole
Definition: EPlayerRole.c:7
SCR_BaseGameMode_OnResourceEnabledChanged
func SCR_BaseGameMode_OnResourceEnabledChanged
Definition: SCR_BaseGameMode.c:129
RplProp
SCR_RplTestEntityClass RplProp
Used for handling entity spawning requests for SCR_CatalogEntitySpawnerComponent and inherited classe...
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_BaseGameMode_OnPlayerRoleChanged
func SCR_BaseGameMode_OnPlayerRoleChanged
Definition: SCR_BaseGameMode.c:126
SCR_BaseScoringSystemComponent
Definition: SCR_BaseScoringSystemComponent.c:26
EGameFlags
EGameFlags
GameMode Game Flags represented by bit mask.
Definition: game.c:16
loadout
string loadout
Definition: SCR_ArsenalManagerComponent.c:2
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
SCR_LoadoutManager
void SCR_LoadoutManager(IEntitySource src, IEntity parent)
Definition: SCR_LoadoutManager.c:500
OnPreloadFinishedInvoker
ScriptInvokerBase< OnPreloadFinished > OnPreloadFinishedInvoker
Definition: SCR_BaseGameMode.c:133
SCR_BaseGameMode_PlayerId
func SCR_BaseGameMode_PlayerId
Definition: SCR_BaseGameMode.c:118
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
func
func
Definition: SCR_AIThreatSystem.c:5
KickCauseCode
KickCauseCode
Definition: KickCauseCode.c:19
SCR_SpawnPreload
Definition: SCR_SpawnPreload.c:1
Instigator
Definition: Instigator.c:6
SCR_BaseGameMode_OnPlayerKilled
func SCR_BaseGameMode_OnPlayerKilled
Definition: SCR_BaseGameMode.c:114
SCR_SpawnData
Definition: SCR_SpawnData.c:9
SCR_AIWorld
Definition: SCR_AIWorld.c:23
m_aDisabledResourceTypes
protected ref array< EResourceType > m_aDisabledResourceTypes
Definition: SCR_ResourceComponent.c:73
ENotification
ENotification
Definition: ENotification.c:4
GetIsClientAuthority
override bool GetIsClientAuthority()
Definition: game.c:268
GameStateTransitions
Definition: GameStateTransitions.c:12
EGameOverTypes
EGameOverTypes
Definition: EGameOverTypes.c:1
SCR_RespawnTimerComponent
void SCR_RespawnTimerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_RespawnTimerComponent.c:333
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_GameModeEndData
Definition: SCR_GameModeEndData.c:4
SCR_SpawnPointSpawnData
Definition: SCR_SpawnPointSpawnData.c:2
m_OnResourceTypeEnabledChanged
protected ref ScriptInvokerBase< SCR_Resources_OnResourceEnabledChanged > m_OnResourceTypeEnabledChanged
Definition: SCR_ResourceComponent.c:82
EResourceType
EResourceType
Definition: SCR_ResourceContainer.c:1
Activate
protected void Activate()
Definition: SCR_BaseHintCondition.c:9
OnPreloadFinished
func OnPreloadFinished
Definition: SCR_BaseGameMode.c:132
SCR_BaseGameMode_OnPlayerDisconnected
func SCR_BaseGameMode_OnPlayerDisconnected
Definition: SCR_BaseGameMode.c:111
SCR_BaseGameModeClass
Definition: SCR_BaseGameMode.c:12
Faction
Definition: Faction.c:12
SCR_BaseGameMode_PlayerIdAndEntity
func SCR_BaseGameMode_PlayerIdAndEntity
Definition: SCR_BaseGameMode.c:122
m_RplComponent
protected RplComponent m_RplComponent
Definition: SCR_CampaignBuildingManagerComponent.c:42
SCR_PlayerFactionAffiliationComponent
Definition: SCR_PlayerFactionAffiliationComponent.c:16
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
data
Get all prefabs that have the spawner data
Definition: SCR_EntityCatalogManagerComponent.c:305
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SCR_FactionManager
void SCR_FactionManager(IEntitySource src, IEntity parent)
Definition: SCR_FactionManager.c:461
SCR_PossessSpawnData
Definition: SCR_PossessSpawnData.c:2
m_fTimeElapsed
float m_fTimeElapsed
Definition: SCR_MineAwarenessComponent.c:9
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
position
vector position
Definition: SCR_DestructibleTreeV2.c:30
SCR_EGameModeState
SCR_EGameModeState
Definition: SCR_EGameModeState.c:4
SCR_BasePlayerLoadout
Definition: SCR_BasePlayerLoadout.c:2
PlayerManager
Definition: PlayerManager.c:12
GetLoadoutManager
SCR_LoadoutManager GetLoadoutManager()
Definition: game.c:163
SCR_ReconnectComponent
Definition: SCR_ReconnectComponent.c:41
Obsolete
RespawnSystemComponentClass GameComponentClass Obsolete()] proto external GenericEntity DoSpawn(string prefab
RespawnSystemComponent should be attached to a gamemode to handle player spawning and respawning.
BaseGameModeClass
Definition: BaseGameMode.c:12
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180
SCR_BaseGameModeComponent
void SCR_BaseGameModeComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Definition: SCR_BaseGameModeComponent.c:199