12 const int SCHEDULER_PLAYERS_PER_TICK = 5;
19 private float m_ArtyBarrageTimer = 0;
22 protected bool m_PlayArty =
false;
23 protected float m_ArtyDelay = 0;
24 protected int m_MinSimultaneousStrikes = 0;
25 protected int m_MaxSimultaneousStrikes = 0;
31 "-500.00 165.00 5231.69",
32 "-500.00 300.00 9934.41",
33 "10406.86 192.00 15860.00",
34 "4811.75 370.00 15860.00",
35 "-500.00 453.00 15860.00"
41 "7440.00 417.00 -500.00",
42 "-500.00 276.00 5473.00",
43 "-500.00 265.00 9852.00",
44 "4953.00 240.00 13300.00",
45 "9620.00 188.00 13300.00",
46 "13300.00 204.00 10322.00",
47 "13300.00 288.00 6204.00",
48 "13300.00 296.00 -500.00"
56 PluginAdditionalInfo m_moduleDefaultCharacter;
86 override void OnMissionStart()
88 super.OnMissionStart();
94 override void OnUpdate(
float timeslice)
96 UpdateDummyScheduler();
97 TickScheduler(timeslice);
98 UpdateLogoutPlayers();
99 m_WorldData.UpdateBaseEnvTemperature(timeslice);
100 m_RainProcHandler.Update(timeslice);
102 RandomArtillery(timeslice);
104 super.OnUpdate(timeslice);
107 override void OnGameplayDataHandlerLoad()
110 GetGame().SetDebugMonitorEnabled(
GetGame().ServerConfigGetInt(
"enableDebugMonitor"));
112 InitialiseWorldData();
116 void RandomArtillery(
float deltaTime)
122 if (m_ArtyBarrageTimer > m_ArtyDelay)
125 m_MaxSimultaneousStrikes =
Math.Clamp(m_MaxSimultaneousStrikes, 1, m_FiringPos.Count());
126 m_MinSimultaneousStrikes =
Math.Clamp(m_MinSimultaneousStrikes, 1, m_MaxSimultaneousStrikes);
133 if (m_MaxSimultaneousStrikes == 1)
136 randPos =
Math.RandomIntInclusive(0, m_FiringPos.Count() - 1);
137 pos =
new Param1<vector>(m_FiringPos[randPos]);
140 GetGame().RPC(
null,
ERPCs.RPC_SOUND_ARTILLERY, params,
true);
152 int randFireNb =
Math.RandomIntInclusive(m_MinSimultaneousStrikes, m_MaxSimultaneousStrikes);
153 for (
int i = 0; i < randFireNb; i++)
155 randPos =
Math.RandomIntInclusive(0, m_FiringPos.Count() - 1);
157 if (usedIndices.Count() <= 0 || usedIndices.Find(randPos) < 0)
160 pos =
new Param1<vector>(m_FiringPos[randPos]);
165 GetGame().RPC(
null,
ERPCs.RPC_SOUND_ARTILLERY, params,
true);
168 usedIndices.Insert(randPos);
174 m_ArtyBarrageTimer = 0.0;
177 m_ArtyBarrageTimer += deltaTime;
181 override bool IsServer()
186 override bool IsPlayerDisconnecting(Man player)
188 return (m_LogoutPlayers && m_LogoutPlayers.Contains(
PlayerBase.Cast(player))) || (m_NewLogoutPlayers && m_NewLogoutPlayers.Contains(
PlayerBase.Cast(player)));
191 void UpdatePlayersStats()
198 foreach (Man man : players)
201 if (
Class.CastTo(player, man))
206 moduleLifespan.UpdateLifespan(player);
210 UpdateCorpseStatesServer();
215 m_LogoutPlayers.Insert(player, info);
216 m_NewLogoutPlayers.Remove(player);
220 void UpdateLogoutPlayers()
222 for (
int i = 0; i < m_LogoutPlayers.Count();)
224 LogoutInfo info = m_LogoutPlayers.GetElement(i);
229 PlayerBase player = m_LogoutPlayers.GetKey(i);
232 identity = player.GetIdentity();
233 m_LogoutPlayers.Remove(player);
237 m_LogoutPlayers.RemoveElement(i);
243 PlayerDisconnected(player, identity, info.param2);
262 Class.CastTo(clientPrepareParams, params);
265 OnClientPrepareEvent(clientPrepareParams.param1, clientPrepareParams.param2, clientPrepareParams.param3, clientPrepareParams.param4, clientPrepareParams.param5);
270 Class.CastTo(newParams, params);
271 player = OnClientNewEvent(newParams.param1, newParams.param2, newParams.param3);
274 Debug.Log(
"ClientNewEvent: Player is empty");
277 identity = newParams.param1;
278 InvokeOnConnect(player,identity);
281 ControlPersonalLight(player);
282 SyncGlobalLighting(player);
288 Class.CastTo(readyParams, params);
289 identity = readyParams.param1;
290 Class.CastTo(player, readyParams.param2);
293 Debug.Log(
"ClientReadyEvent: Player is empty");
297 OnClientReadyEvent(identity, player);
298 InvokeOnConnect(player, identity);
301 ControlPersonalLight(player);
302 SyncGlobalLighting(player);
307 Class.CastTo(respawnParams, params);
308 identity = respawnParams.param1;
309 Class.CastTo(player, respawnParams.param2);
312 Debug.Log(
"ClientRespawnEvent: Player is empty");
316 OnClientRespawnEvent(identity, player);
321 Class.CastTo(reconnectParams, params);
323 identity = reconnectParams.param1;
324 Class.CastTo(player, reconnectParams.param2);
327 Debug.Log(
"ClientReconnectEvent: Player is empty");
331 OnClientReconnectEvent(identity, player);
336 Class.CastTo(discoParams, params);
338 identity = discoParams.param1;
339 Class.CastTo(player, discoParams.param2);
340 int logoutTime = discoParams.param3;
341 bool authFailed = discoParams.param4;
345 Debug.Log(
"ClientDisconnectenEvent: Player is empty");
349 OnClientDisconnectedEvent(identity, player, logoutTime, authFailed);
355 Class.CastTo(logoutCancelParams, params);
356 Class.CastTo(player, logoutCancelParams.param1);
357 identity = player.GetIdentity();
362 Print(
"[Logout]: Player " + identity.GetId() +
" cancelled");
366 Print(
"[Logout]: Player cancelled");
368 m_LogoutPlayers.Remove(player);
369 m_NewLogoutPlayers.Remove(player);
385 player.OnDisconnect();
388 void OnClientPrepareEvent(
PlayerIdentity identity, out
bool useDB, out
vector pos, out
float yaw, out
int preloadTimeout)
399 pos =
"1189.3 0.0 5392.48";
409 bool is_personal_light = !
GetGame().ServerConfigGetInt(
"disablePersonalLight");
410 Param1<bool> personal_light_toggle =
new Param1<bool>(is_personal_light);
411 GetGame().RPCSingleParam(player,
ERPCs.RPC_TOGGLE_PERSONAL_LIGHT, personal_light_toggle,
true, player.GetIdentity());
415 Error(
"Error! Player was not initialized at the right time. Thus cannot send RPC command to enable or disable personal light!");
424 int lightingID =
GetGame().ServerConfigGetInt(
"lightingConfig");
425 Param1<int> lightID =
new Param1<int>(lightingID);
426 GetGame().RPCSingleParam(player,
ERPCs.RPC_SEND_LIGHTING_SETUP, lightID,
true, player.GetIdentity());
434 return GetGame().GetMenuDefaultCharacterData(
false).DeserializeCharacterData(ctx);
441 playerEnt =
GetGame().CreatePlayer(identity, characterName, pos, 0,
"NONE");
453 string attachment_type;
454 for (
int i = 0; i < DefaultCharacterCreationMethods.GetAttachmentSlotsArray().
Count(); i++)
456 slot_ID = DefaultCharacterCreationMethods.GetAttachmentSlotsArray().Get(i);
457 attachment_type =
"";
458 if (m_RespawnMode !=
GameConstants.RESPAWN_MODE_CUSTOM || !char_data.GetAttachmentMap().Find(slot_ID,attachment_type) || !VerifyAttachmentType(slot_ID,attachment_type))
461 if (DefaultCharacterCreationMethods.GetConfigArrayCountFromSlotID(slot_ID) > 0)
463 attachment_type = DefaultCharacterCreationMethods.GetConfigAttachmentTypes(slot_ID).GetRandomElement();
469 if (attachment_type !=
"")
471 m_player.GetInventory().CreateAttachmentEx(attachment_type,slot_ID);
479 void StartingEquipSetup(
PlayerBase player,
bool clothesChosen)
483 bool VerifyAttachmentType(
int slot_ID,
string attachment_type)
485 return DefaultCharacterCreationMethods.GetConfigAttachmentTypes(slot_ID).Find(attachment_type) > -1;
490 string characterType =
GetGame().CreateRandomPlayer();
491 bool generateRandomEquip =
false;
494 if (ProcessLoginData(ctx) && (m_RespawnMode ==
GameConstants.RESPAWN_MODE_CUSTOM) && !
GetGame().GetMenuDefaultCharacterData(
false).IsRandomCharacterForced())
496 if (
GetGame().ListAvailableCharacters().Find(
GetGame().GetMenuDefaultCharacterData().GetCharacterType()) > -1)
497 characterType =
GetGame().GetMenuDefaultCharacterData().GetCharacterType();
501 generateRandomEquip =
true;
507 if (presetData && presetData.IsValid())
509 string presetCharType = presetData.GetRandomCharacterType();
510 if (presetCharType ==
string.
Empty)
511 presetCharType = characterType;
512 if (CreateCharacter(identity, pos, ctx, presetCharType) !=
null)
519 ErrorEx(
"Failed to create character from type: " + presetCharType +
", using default spawning method");
524 ErrorEx(
"Failed to load PlayerSpawnPreset data properly, using default spawning method");
528 if (CreateCharacter(identity, pos, ctx, characterType))
530 if (generateRandomEquip)
531 GetGame().GetMenuDefaultCharacterData().GenerateRandomEquip();
532 EquipCharacter(
GetGame().GetMenuDefaultCharacterData());
540 GetGame().SelectPlayer(identity, player);
542 #ifdef DIAG_DEVELOPER
543 if (FeatureTimeAccel.m_CurrentTimeAccel)
545 GetGame().RPCSingleParam(player,
ERPCs.DIAG_TIMEACCEL_CLIENT_SYNC, FeatureTimeAccel.m_CurrentTimeAccel,
true, identity);
554 if (player.IsUnconscious() || player.IsRestrained())
557 player.SetHealth(
"",
"", 0.0);
561 #ifdef DIAG_DEVELOPER
562 if (FeatureTimeAccel.m_CurrentTimeAccel)
564 GetGame().RPCSingleParam(player,
ERPCs.DIAG_TIMEACCEL_CLIENT_SYNC, FeatureTimeAccel.m_CurrentTimeAccel,
true, identity);
573 player.OnReconnect();
579 bool disconnectNow =
true;
585 if (player.IsAlive())
587 if (!m_LogoutPlayers.Contains(player) && !m_NewLogoutPlayers.Contains(player))
589 Print(
"[Logout]: New player " + identity.GetId() +
" with logout time " + logoutTime.ToString());
592 player.StatSyncToClient();
595 GetGame().SendLogoutTime(player, logoutTime);
600 m_NewLogoutPlayers.Insert(player, params);
609 disconnectNow =
false;
617 Print(
"[Logout]: New player " + identity.GetId() +
" with instant logout");
620 GetGame().SendLogoutTime(player, 0);
622 PlayerDisconnected(player, identity, identity.GetId());
631 Print(
"[Logout]: Skipping player " + uid +
", already removed");
639 InvokeOnDisconnect(player);
641 Print(
"[Logout]: Player " + uid +
" finished");
649 GetHive().CharacterExit(player);
653 player.ReleaseNetworkControls();
657 GetGame().DisconnectPlayer(identity, uid);
664 if (player.IsUnconscious() || player.IsRestrained())
666 switch (player.GetKickOffReason())
686 if (player.IsAlive())
688 if (ShouldPlayerBeKilled(player))
690 player.SetHealth(
"",
"", 0.0);
699 void TickScheduler(
float timeslice)
701 GetGame().GetWorld().GetPlayerList(m_Players);
702 int players_count = m_Players.Count();
703 int tick_count_max =
Math.Min(players_count, SCHEDULER_PLAYERS_PER_TICK);
705 for (
int i = 0; i < tick_count_max; i++)
707 if (m_currentPlayer >= players_count)
715 currentPlayer.OnTick();
721 override bool InsertCorpse(Man player)
724 return m_DeadPlayersArray.Insert(corpse_data) >= 0;
727 void UpdateCorpseStatesServer()
729 if (m_DeadPlayersArray.Count() == 0)
731 int current_time =
GetGame().GetTime();
735 for (
int i = 0; i < m_DeadPlayersArray.Count(); i++)
737 corpse_data = m_DeadPlayersArray.Get(i);
738 if (!corpse_data || (corpse_data && (!corpse_data.m_Player || !corpse_data.m_bUpdate)))
740 invalid_corpses.Insert(i);
742 else if (corpse_data.m_bUpdate && current_time - corpse_data.m_iLastUpdateTime >= 30000)
744 corpse_data.UpdateCorpseState();
745 corpse_data.m_iLastUpdateTime = current_time;
750 if (invalid_corpses.Count() > 0)
752 for (i = invalid_corpses.Count() - 1; i > -1; i--)
754 m_DeadPlayersArray.Remove(invalid_corpses.Get(i));
763 rpc.Write(m_RespawnMode);
764 rpc.Send(
null,
ERPCs.RPC_SERVER_RESPAWN_MODE,
true, identity);
769 return m_RainProcHandler;