269 lines
6.0 KiB
C#
269 lines
6.0 KiB
C#
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<Collider, vp_Respawner> m_Instances;
|
|
|
|
protected static vp_Respawner m_GetInstanceResult;
|
|
|
|
protected Renderer m_Renderer;
|
|
|
|
public static Dictionary<Collider, vp_Respawner> Instances
|
|
{
|
|
get
|
|
{
|
|
if (m_Instances == null)
|
|
{
|
|
m_Instances = new Dictionary<Collider, vp_Respawner>(100);
|
|
}
|
|
return m_Instances;
|
|
}
|
|
}
|
|
|
|
public Renderer Renderer
|
|
{
|
|
get
|
|
{
|
|
if (m_Renderer == null)
|
|
{
|
|
m_Renderer = GetComponent<Renderer>();
|
|
}
|
|
return m_Renderer;
|
|
}
|
|
}
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
m_Transform = base.transform;
|
|
m_Audio = GetComponent<AudioSource>();
|
|
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<Collider>() != null && !Instances.ContainsValue(this))
|
|
{
|
|
Instances.Add(GetComponent<Collider>(), 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<Transform, vp_Placement>.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<Rigidbody>() != null && !GetComponent<Rigidbody>().isKinematic)
|
|
{
|
|
GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
|
|
GetComponent<Rigidbody>().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<vp_Respawner>();
|
|
Instances.Add(col, m_GetInstanceResult);
|
|
}
|
|
return m_GetInstanceResult;
|
|
}
|
|
|
|
protected void OnLevelWasLoaded()
|
|
{
|
|
Instances.Clear();
|
|
}
|
|
}
|