using System; using System.Collections.Generic; using UnityEngine; [Serializable] public class vp_Respawner : MonoBehaviour { public enum SpawnMode { SamePosition = 0, SpawnPoint = 1 } public enum ObstructionSolver { Wait = 0, AdjustPlacement = 1 } public SpawnMode m_SpawnMode; public string SpawnPointTag = string.Empty; public ObstructionSolver m_ObstructionSolver; public float ObstructionRadius = 1f; public float MinRespawnTime = 3f; public float MaxRespawnTime = 3f; public float LastRespawnTime; public bool SpawnOnAwake; public AudioClip SpawnSound; public GameObject[] SpawnFXPrefabs; protected Vector3 m_InitialPosition = Vector3.zero; protected Quaternion m_InitialRotation; protected vp_Placement Placement = new vp_Placement(); protected Transform m_Transform; protected AudioSource m_Audio; protected bool m_IsInitialSpawnOnAwake; protected vp_Timer.Handle m_RespawnTimer = new vp_Timer.Handle(); protected static Dictionary m_Instances; protected static vp_Respawner m_GetInstanceResult; protected Renderer m_Renderer; public static Dictionary Instances { get { if (m_Instances == null) { m_Instances = new Dictionary(100); } return m_Instances; } } public Renderer Renderer { get { if (m_Renderer == null) { m_Renderer = GetComponent(); } return m_Renderer; } } protected virtual void Awake() { m_Transform = base.transform; m_Audio = GetComponent(); Placement.Position = (m_InitialPosition = m_Transform.position); Placement.Rotation = (m_InitialRotation = m_Transform.rotation); if (m_SpawnMode == SpawnMode.SamePosition) { SpawnPointTag = string.Empty; } if (SpawnOnAwake) { m_IsInitialSpawnOnAwake = true; vp_Utility.Activate(base.gameObject, false); PickSpawnPoint(); } } protected virtual void OnEnable() { if (GetComponent() != null && !Instances.ContainsValue(this)) { Instances.Add(GetComponent(), this); } } protected virtual void OnDisable() { } protected virtual void SpawnFX() { if (!m_IsInitialSpawnOnAwake) { if (m_Audio != null) { m_Audio.pitch = Time.timeScale; m_Audio.PlayOneShot(SpawnSound); } if (SpawnFXPrefabs != null && SpawnFXPrefabs.Length > 0) { GameObject[] spawnFXPrefabs = SpawnFXPrefabs; foreach (GameObject gameObject in spawnFXPrefabs) { if (gameObject != null) { vp_Utility.Instantiate(gameObject, m_Transform.position, m_Transform.rotation); } } } } m_IsInitialSpawnOnAwake = false; } protected virtual void Die() { vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer); } public virtual void PickSpawnPoint() { if (this == null) { return; } if (m_SpawnMode == SpawnMode.SamePosition || vp_SpawnPoint.SpawnPoints.Count < 1) { Placement.Position = m_InitialPosition; Placement.Rotation = m_InitialRotation; if (Placement.IsObstructed(ObstructionRadius)) { switch (m_ObstructionSolver) { case ObstructionSolver.Wait: vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer); return; case ObstructionSolver.AdjustPlacement: if (!vp_Placement.AdjustPosition(Placement, ObstructionRadius)) { vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer); return; } break; } } } else { switch (m_ObstructionSolver) { case ObstructionSolver.Wait: Placement = vp_SpawnPoint.GetRandomPlacement(0f, SpawnPointTag); if (Placement == null) { Placement = new vp_Placement(); m_SpawnMode = SpawnMode.SamePosition; PickSpawnPoint(); } if (Placement.IsObstructed(ObstructionRadius)) { vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer); return; } break; case ObstructionSolver.AdjustPlacement: Placement = vp_SpawnPoint.GetRandomPlacement(ObstructionRadius, SpawnPointTag); if (Placement == null) { vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer); return; } break; } } Respawn(); } public virtual void PickSpawnPoint(Vector3 position, Quaternion rotation) { Placement.Position = position; Placement.Rotation = rotation; Respawn(); } public virtual void Respawn() { LastRespawnTime = Time.time; vp_Utility.Activate(base.gameObject); SpawnFX(); if (vp_Gameplay.isMultiplayer && vp_Gameplay.isMaster) { vp_GlobalEvent.Send("TransmitRespawn", base.transform.root, Placement); } SendMessage("Reset"); Placement.Position = m_InitialPosition; Placement.Rotation = m_InitialRotation; } public virtual void Reset() { if (Application.isPlaying) { m_Transform.position = Placement.Position; m_Transform.rotation = Placement.Rotation; if (GetComponent() != null && !GetComponent().isKinematic) { GetComponent().angularVelocity = Vector3.zero; GetComponent().velocity = Vector3.zero; } } } public static void ResetAll(bool reInitTimers = false) { foreach (vp_Respawner value in Instances.Values) { if (!(value == null) && (!vp_Utility.IsActive(value.gameObject) || (value is vp_PlayerRespawner && (value as vp_PlayerRespawner).Player.Dead.Active))) { if (reInitTimers) { value.Die(); } else { value.PickSpawnPoint(); } } } } public static vp_Respawner GetByCollider(Collider col) { if (!Instances.TryGetValue(col, out m_GetInstanceResult)) { m_GetInstanceResult = col.transform.root.GetComponentInChildren(); Instances.Add(col, m_GetInstanceResult); } return m_GetInstanceResult; } protected void OnLevelWasLoaded() { Instances.Clear(); } }