using System.Collections.Generic; using UnityEngine; using SanAndreasUnity.Net; using SanAndreasUnity.Utilities; using System.Linq; namespace SanAndreasUnity.Behaviours { public class SpawnManager : MonoBehaviour { public static SpawnManager Instance { get; private set; } public bool spawnPlayerWhenConnected = true; public bool IsSpawningPaused { get; set; } = false; public float spawnInterval = 4f; float m_lastSpawnTime = 0f; void Awake() { Instance = this; } void Start() { this.InvokeRepeating(nameof(RepeatedMethod), 1f, 1f); Player.onStart += OnPlayerConnected; } void OnLoaderFinished() { if (!NetStatus.IsServer) return; // spawn players that were connected during loading process - this will always be the case for // local player SpawnPlayers(); } Transform GetSpawnFocusPos() { if (Ped.Instance) return Ped.Instance.transform; if (Camera.main) return Camera.main.transform; return null; } void RepeatedMethod() { if (!NetStatus.IsServer) return; if (this.IsSpawningPaused) return; if (Time.time - m_lastSpawnTime >= this.spawnInterval) { // enough time passed m_lastSpawnTime = Time.time; F.RunExceptionSafe(() => this.SpawnPlayers()); } } bool GetSpawnPositionFromFocus(out TransformDataStruct transformData) { Transform focusPos = GetSpawnFocusPos(); if (null == focusPos) { transformData = new TransformDataStruct(); return false; } transformData = new TransformDataStruct( focusPos.position + Random.insideUnitCircle.ToVector3XZ() * 15f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); return true; } bool GetSpawnPositionFromInteriors(out TransformDataStruct transformData) { transformData = World.Cell.GetEnexExitTransform( World.Cell.Instance.GetEnexesFromLoadedInteriors() .ToList() .RandomElement()); return true; } public bool GetSpawnPosition(out TransformDataStruct transformData) { if (null == World.Cell.Instance || World.Cell.Instance.HasExterior) return GetSpawnPositionFromFocus(out transformData); else return GetSpawnPositionFromInteriors(out transformData); } void SpawnPlayers() { if (!NetStatus.IsServer) return; if (!Loader.HasLoaded) return; TransformDataStruct transformData; foreach (var player in Player.AllPlayers) { if (this.GetSpawnPosition(out transformData)) SpawnPlayer(player, transformData); else break; } } public static Ped SpawnPlayer (Player player, TransformDataStruct spawnPlace) { if (player.OwnedPed != null) return null; var ped = Ped.SpawnPed(Ped.RandomPedId, spawnPlace.position, spawnPlace.rotation, false); ped.NetPlayerOwnerGameObject = player.gameObject; ped.WeaponHolder.autoAddWeapon = true; // this ped should not be destroyed when he gets out of range ped.gameObject.DestroyComponent(); NetManager.Spawn(ped.gameObject); player.OwnedPed = ped; Debug.LogFormat("Spawned ped {0} for player {1}, time: {2}", ped.DescriptionForLogging, player.DescriptionForLogging, F.CurrentDateForLogging); return ped; } void OnPlayerConnected(Player player) { if (!NetStatus.IsServer) return; if (!Loader.HasLoaded) // these players will be spawned when loading process finishes return; if (!this.spawnPlayerWhenConnected) return; if (this.GetSpawnPosition(out TransformDataStruct transformData)) SpawnPlayer(player, transformData); } } }