464 lines
12 KiB
C#
464 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class vp_DamageHandler : MonoBehaviour
|
|
{
|
|
public float MaxHealth = 1f;
|
|
|
|
public GameObject[] DeathSpawnObjects;
|
|
|
|
public float MinDeathDelay;
|
|
|
|
public float MaxDeathDelay;
|
|
|
|
public float CurrentHealth;
|
|
|
|
protected bool m_InstaKill;
|
|
|
|
public AudioClip DeathSound;
|
|
|
|
protected AudioSource m_Audio;
|
|
|
|
public float ImpactDamageThreshold = 10f;
|
|
|
|
public float ImpactDamageMultiplier;
|
|
|
|
[HideInInspector]
|
|
public bool Respawns;
|
|
|
|
[HideInInspector]
|
|
public float MinRespawnTime = -99999f;
|
|
|
|
[HideInInspector]
|
|
public float MaxRespawnTime = -99999f;
|
|
|
|
[HideInInspector]
|
|
public float RespawnCheckRadius = -99999f;
|
|
|
|
[HideInInspector]
|
|
public AudioClip RespawnSound;
|
|
|
|
[HideInInspector]
|
|
public GameObject DeathEffect;
|
|
|
|
protected static Dictionary<Collider, vp_DamageHandler> m_Instances;
|
|
|
|
protected static vp_DamageHandler m_GetDamageHandlerOfColliderResult;
|
|
|
|
protected Vector3 m_StartPosition;
|
|
|
|
protected Quaternion m_StartRotation;
|
|
|
|
protected Transform m_Transform;
|
|
|
|
protected vp_Respawner m_Respawner;
|
|
|
|
protected Transform m_Source;
|
|
|
|
protected Transform m_OriginalSource;
|
|
|
|
public static Dictionary<Collider, vp_DamageHandler> Instances
|
|
{
|
|
get
|
|
{
|
|
if (m_Instances == null)
|
|
{
|
|
m_Instances = new Dictionary<Collider, vp_DamageHandler>(100);
|
|
}
|
|
return m_Instances;
|
|
}
|
|
}
|
|
|
|
public Transform Transform
|
|
{
|
|
get
|
|
{
|
|
if (m_Transform == null)
|
|
{
|
|
m_Transform = base.transform;
|
|
}
|
|
return m_Transform;
|
|
}
|
|
}
|
|
|
|
public vp_Respawner Respawner
|
|
{
|
|
get
|
|
{
|
|
if (m_Respawner == null)
|
|
{
|
|
m_Respawner = GetComponent<vp_Respawner>();
|
|
}
|
|
return m_Respawner;
|
|
}
|
|
}
|
|
|
|
protected Transform Source
|
|
{
|
|
get
|
|
{
|
|
if (m_Source == null)
|
|
{
|
|
m_Source = Transform;
|
|
}
|
|
return m_Source;
|
|
}
|
|
set
|
|
{
|
|
m_Source = value;
|
|
}
|
|
}
|
|
|
|
protected Transform OriginalSource
|
|
{
|
|
get
|
|
{
|
|
if (m_OriginalSource == null)
|
|
{
|
|
m_OriginalSource = Transform;
|
|
}
|
|
return m_OriginalSource;
|
|
}
|
|
set
|
|
{
|
|
m_OriginalSource = value;
|
|
}
|
|
}
|
|
|
|
[Obsolete("This property will be removed in an upcoming release.")]
|
|
public Transform Sender
|
|
{
|
|
get
|
|
{
|
|
return Source;
|
|
}
|
|
set
|
|
{
|
|
Source = value;
|
|
}
|
|
}
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
m_Audio = GetComponent<AudioSource>();
|
|
CurrentHealth = MaxHealth;
|
|
CheckForObsoleteParams();
|
|
Instances.Add(GetComponent<Collider>(), this);
|
|
}
|
|
|
|
protected virtual void OnEnable()
|
|
{
|
|
}
|
|
|
|
protected virtual void OnDisable()
|
|
{
|
|
}
|
|
|
|
public virtual void Damage(float damage)
|
|
{
|
|
Damage(new vp_DamageInfo(damage, null));
|
|
}
|
|
|
|
public virtual void Damage(vp_DamageInfo damageInfo)
|
|
{
|
|
if (!base.enabled || !vp_Utility.IsActive(base.gameObject) || !vp_Gameplay.isMaster || CurrentHealth <= 0f)
|
|
{
|
|
return;
|
|
}
|
|
if (damageInfo != null)
|
|
{
|
|
if (damageInfo.Source != null)
|
|
{
|
|
Source = damageInfo.Source;
|
|
}
|
|
if (damageInfo.OriginalSource != null)
|
|
{
|
|
OriginalSource = damageInfo.OriginalSource;
|
|
}
|
|
}
|
|
if (damageInfo.Type == vp_DamageInfo.DamageType.Bullet && m_Source == Transform)
|
|
{
|
|
return;
|
|
}
|
|
CurrentHealth = Mathf.Min(CurrentHealth - damageInfo.Damage, MaxHealth);
|
|
if (vp_Gameplay.isMultiplayer && damageInfo.Source != null)
|
|
{
|
|
vp_GlobalEvent<Transform, Transform, float>.Send("TransmitDamage", Transform.root, damageInfo.OriginalSource, damageInfo.Damage);
|
|
}
|
|
if (!(CurrentHealth <= 0f))
|
|
{
|
|
return;
|
|
}
|
|
if (m_InstaKill)
|
|
{
|
|
SendMessage("Die");
|
|
return;
|
|
}
|
|
vp_Timer.In(UnityEngine.Random.Range(MinDeathDelay, MaxDeathDelay), delegate
|
|
{
|
|
SendMessage("Die");
|
|
});
|
|
}
|
|
|
|
public virtual void DieBySources(Transform[] sourceAndOriginalSource)
|
|
{
|
|
if (sourceAndOriginalSource.Length != 2)
|
|
{
|
|
Debug.LogWarning(string.Concat("Warning (", this, ") 'DieBySources' argument must contain 2 transforms."));
|
|
return;
|
|
}
|
|
Source = sourceAndOriginalSource[0];
|
|
OriginalSource = sourceAndOriginalSource[1];
|
|
Die();
|
|
}
|
|
|
|
public virtual void DieBySource(Transform source)
|
|
{
|
|
Transform originalSource = (Source = source);
|
|
OriginalSource = originalSource;
|
|
Die();
|
|
}
|
|
|
|
public virtual void Die()
|
|
{
|
|
if (!base.enabled || !vp_Utility.IsActive(base.gameObject))
|
|
{
|
|
return;
|
|
}
|
|
if (m_Audio != null)
|
|
{
|
|
m_Audio.pitch = Time.timeScale;
|
|
m_Audio.PlayOneShot(DeathSound);
|
|
}
|
|
GameObject[] deathSpawnObjects = DeathSpawnObjects;
|
|
foreach (GameObject gameObject in deathSpawnObjects)
|
|
{
|
|
if (gameObject != null)
|
|
{
|
|
GameObject gameObject2 = (GameObject)vp_Utility.Instantiate(gameObject, Transform.position, Transform.rotation);
|
|
if (Source != null && gameObject2 != null)
|
|
{
|
|
vp_TargetEvent<Transform>.Send(gameObject2.transform, "SetSource", OriginalSource);
|
|
}
|
|
}
|
|
}
|
|
if (Respawner == null)
|
|
{
|
|
vp_Utility.Destroy(base.gameObject);
|
|
}
|
|
else
|
|
{
|
|
RemoveBulletHoles();
|
|
vp_Utility.Activate(base.gameObject, false);
|
|
}
|
|
m_InstaKill = false;
|
|
if (vp_Gameplay.isMultiplayer && vp_Gameplay.isMaster)
|
|
{
|
|
vp_GlobalEvent<Transform>.Send("TransmitKill", base.transform.root);
|
|
}
|
|
}
|
|
|
|
protected virtual void Reset()
|
|
{
|
|
CurrentHealth = MaxHealth;
|
|
Source = null;
|
|
OriginalSource = null;
|
|
}
|
|
|
|
protected virtual void RemoveBulletHoles()
|
|
{
|
|
vp_HitscanBullet[] componentsInChildren = GetComponentsInChildren<vp_HitscanBullet>(true);
|
|
for (int i = 0; i < componentsInChildren.Length; i++)
|
|
{
|
|
vp_Utility.Destroy(componentsInChildren[i].gameObject);
|
|
}
|
|
}
|
|
|
|
protected virtual void OnCollisionEnter(Collision collision)
|
|
{
|
|
float num = collision.relativeVelocity.sqrMagnitude * 0.1f;
|
|
float num2 = ((!(num > ImpactDamageThreshold)) ? 0f : (num * ImpactDamageMultiplier));
|
|
if (!(num2 <= 0f))
|
|
{
|
|
if (CurrentHealth - num2 <= 0f)
|
|
{
|
|
m_InstaKill = true;
|
|
}
|
|
Damage(new vp_DamageInfo(num2, collision.collider.transform, vp_DamageInfo.DamageType.Impact));
|
|
}
|
|
}
|
|
|
|
public static vp_DamageHandler GetDamageHandlerOfCollider(Collider col)
|
|
{
|
|
m_GetDamageHandlerOfColliderResult = null;
|
|
if (!Instances.TryGetValue(col, out m_GetDamageHandlerOfColliderResult))
|
|
{
|
|
Transform parent = col.transform;
|
|
while (parent != null && m_GetDamageHandlerOfColliderResult == null)
|
|
{
|
|
m_GetDamageHandlerOfColliderResult = parent.GetComponent<vp_DamageHandler>();
|
|
parent = parent.parent;
|
|
}
|
|
Instances.Add(col, m_GetDamageHandlerOfColliderResult);
|
|
}
|
|
return m_GetDamageHandlerOfColliderResult;
|
|
}
|
|
|
|
protected void OnLevelWasLoaded()
|
|
{
|
|
Instances.Clear();
|
|
}
|
|
|
|
protected virtual void Respawn()
|
|
{
|
|
}
|
|
|
|
protected virtual void Reactivate()
|
|
{
|
|
}
|
|
|
|
private void CheckForObsoleteParams()
|
|
{
|
|
if (DeathEffect != null)
|
|
{
|
|
Debug.LogWarning(string.Concat(this, "'DeathEffect' is obsolete! Please use the 'DeathSpawnObjects' array instead."));
|
|
}
|
|
string text = string.Empty;
|
|
if (Respawns)
|
|
{
|
|
text += "Respawns, ";
|
|
}
|
|
if (MinRespawnTime != -99999f)
|
|
{
|
|
text += "MinRespawnTime, ";
|
|
}
|
|
if (MaxRespawnTime != -99999f)
|
|
{
|
|
text += "MaxRespawnTime, ";
|
|
}
|
|
if (RespawnCheckRadius != -99999f)
|
|
{
|
|
text += "RespawnCheckRadius, ";
|
|
}
|
|
if (RespawnSound != null)
|
|
{
|
|
text += "RespawnSound, ";
|
|
}
|
|
if (text != string.Empty)
|
|
{
|
|
text = text.Remove(text.LastIndexOf(", "));
|
|
Debug.LogWarning(string.Format(string.Concat("Warning + (", this, ") The following parameters are obsolete: \"{0}\". Creating a temp vp_Respawner component. To remove this warning, see the UFPS menu -> Wizards -> Convert Old DamageHandlers."), text));
|
|
CreateTempRespawner();
|
|
}
|
|
}
|
|
|
|
public bool CreateTempRespawner()
|
|
{
|
|
if ((bool)GetComponent<vp_Respawner>() || (bool)GetComponent<vp_PlayerRespawner>())
|
|
{
|
|
DisableOldParams();
|
|
return false;
|
|
}
|
|
CreateRespawnerForDamageHandler(this);
|
|
DisableOldParams();
|
|
return true;
|
|
}
|
|
|
|
public static int GenerateRespawnersForAllDamageHandlers()
|
|
{
|
|
vp_PlayerDamageHandler[] array = UnityEngine.Object.FindObjectsOfType(typeof(vp_PlayerDamageHandler)) as vp_PlayerDamageHandler[];
|
|
if (array != null && array.Length > 0)
|
|
{
|
|
vp_PlayerDamageHandler[] array2 = array;
|
|
foreach (vp_PlayerDamageHandler vp_PlayerDamageHandler2 in array2)
|
|
{
|
|
if (!(vp_PlayerDamageHandler2.transform.GetComponent<vp_FPPlayerEventHandler>() == null))
|
|
{
|
|
vp_FPPlayerDamageHandler vp_FPPlayerDamageHandler2 = vp_PlayerDamageHandler2.gameObject.AddComponent<vp_FPPlayerDamageHandler>();
|
|
vp_FPPlayerDamageHandler2.AllowFallDamage = vp_PlayerDamageHandler2.AllowFallDamage;
|
|
vp_FPPlayerDamageHandler2.DeathEffect = vp_PlayerDamageHandler2.DeathEffect;
|
|
vp_FPPlayerDamageHandler2.DeathSound = vp_PlayerDamageHandler2.DeathSound;
|
|
vp_FPPlayerDamageHandler2.DeathSpawnObjects = vp_PlayerDamageHandler2.DeathSpawnObjects;
|
|
vp_FPPlayerDamageHandler2.FallImpactPitch = vp_PlayerDamageHandler2.FallImpactPitch;
|
|
vp_FPPlayerDamageHandler2.FallImpactSounds = vp_PlayerDamageHandler2.FallImpactSounds;
|
|
vp_FPPlayerDamageHandler2.FallImpactThreshold = vp_PlayerDamageHandler2.FallImpactThreshold;
|
|
vp_FPPlayerDamageHandler2.ImpactDamageMultiplier = vp_PlayerDamageHandler2.ImpactDamageMultiplier;
|
|
vp_FPPlayerDamageHandler2.ImpactDamageThreshold = vp_PlayerDamageHandler2.ImpactDamageThreshold;
|
|
vp_FPPlayerDamageHandler2.m_Audio = vp_PlayerDamageHandler2.m_Audio;
|
|
vp_FPPlayerDamageHandler2.CurrentHealth = vp_PlayerDamageHandler2.CurrentHealth;
|
|
vp_FPPlayerDamageHandler2.m_StartPosition = vp_PlayerDamageHandler2.m_StartPosition;
|
|
vp_FPPlayerDamageHandler2.m_StartRotation = vp_PlayerDamageHandler2.m_StartRotation;
|
|
vp_FPPlayerDamageHandler2.MaxDeathDelay = vp_PlayerDamageHandler2.MaxDeathDelay;
|
|
vp_FPPlayerDamageHandler2.MaxHealth = vp_PlayerDamageHandler2.MaxHealth;
|
|
vp_FPPlayerDamageHandler2.MaxRespawnTime = vp_PlayerDamageHandler2.MaxRespawnTime;
|
|
vp_FPPlayerDamageHandler2.MinDeathDelay = vp_PlayerDamageHandler2.MinDeathDelay;
|
|
vp_FPPlayerDamageHandler2.MinRespawnTime = vp_PlayerDamageHandler2.MinRespawnTime;
|
|
vp_FPPlayerDamageHandler2.RespawnCheckRadius = vp_PlayerDamageHandler2.RespawnCheckRadius;
|
|
vp_FPPlayerDamageHandler2.Respawns = vp_PlayerDamageHandler2.Respawns;
|
|
vp_FPPlayerDamageHandler2.RespawnSound = vp_PlayerDamageHandler2.RespawnSound;
|
|
UnityEngine.Object.DestroyImmediate(vp_PlayerDamageHandler2);
|
|
}
|
|
}
|
|
}
|
|
vp_DamageHandler[] array3 = UnityEngine.Object.FindObjectsOfType(typeof(vp_DamageHandler)) as vp_DamageHandler[];
|
|
vp_DamageHandler[] array4 = UnityEngine.Object.FindObjectsOfType(typeof(vp_FPPlayerDamageHandler)) as vp_DamageHandler[];
|
|
int num = 0;
|
|
vp_DamageHandler[] array5 = array3;
|
|
foreach (vp_DamageHandler vp_DamageHandler2 in array5)
|
|
{
|
|
if (vp_DamageHandler2.CreateTempRespawner())
|
|
{
|
|
num++;
|
|
}
|
|
}
|
|
vp_DamageHandler[] array6 = array4;
|
|
foreach (vp_DamageHandler vp_DamageHandler3 in array6)
|
|
{
|
|
if (vp_DamageHandler3.CreateTempRespawner())
|
|
{
|
|
num++;
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private void DisableOldParams()
|
|
{
|
|
Respawns = false;
|
|
MinRespawnTime = -99999f;
|
|
MaxRespawnTime = -99999f;
|
|
RespawnCheckRadius = -99999f;
|
|
RespawnSound = null;
|
|
}
|
|
|
|
private static void CreateRespawnerForDamageHandler(vp_DamageHandler damageHandler)
|
|
{
|
|
if ((bool)damageHandler.gameObject.GetComponent<vp_Respawner>() || (bool)damageHandler.gameObject.GetComponent<vp_PlayerRespawner>())
|
|
{
|
|
return;
|
|
}
|
|
vp_Respawner vp_Respawner2 = null;
|
|
vp_Respawner2 = ((!(damageHandler is vp_FPPlayerDamageHandler)) ? damageHandler.gameObject.AddComponent<vp_Respawner>() : damageHandler.gameObject.AddComponent<vp_PlayerRespawner>());
|
|
if (!(vp_Respawner2 == null))
|
|
{
|
|
if (damageHandler.MinRespawnTime != -99999f)
|
|
{
|
|
vp_Respawner2.MinRespawnTime = damageHandler.MinRespawnTime;
|
|
}
|
|
if (damageHandler.MaxRespawnTime != -99999f)
|
|
{
|
|
vp_Respawner2.MaxRespawnTime = damageHandler.MaxRespawnTime;
|
|
}
|
|
if (damageHandler.RespawnCheckRadius != -99999f)
|
|
{
|
|
vp_Respawner2.ObstructionRadius = damageHandler.RespawnCheckRadius;
|
|
}
|
|
if (damageHandler.RespawnSound != null)
|
|
{
|
|
vp_Respawner2.SpawnSound = damageHandler.RespawnSound;
|
|
}
|
|
}
|
|
}
|
|
}
|