SanAndreasUnity/Assets/Scripts/Behaviours/SpawnManager.cs

162 lines
4.7 KiB
C#

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<OutOfRangeDestroyer>();
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);
}
}
}