2020-05-17 00:14:00 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Events;
|
|
|
|
|
|
|
|
|
|
namespace SanAndreasUnity.Utilities
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public class DamageInfo
|
|
|
|
|
{
|
|
|
|
|
public float amount = 0f;
|
2020-06-29 15:11:29 +00:00
|
|
|
|
public string damageType = null;
|
2020-05-17 00:14:00 +00:00
|
|
|
|
public Transform raycastHitTransform = null;
|
2021-01-04 00:28:58 +00:00
|
|
|
|
public Vector3 hitDirection = Vector3.forward;
|
2020-07-01 16:52:35 +00:00
|
|
|
|
public Vector3 hitPoint = Vector3.zero;
|
|
|
|
|
public Vector3 hitNormal = Vector3.up;
|
2020-05-18 23:00:24 +00:00
|
|
|
|
public object attacker = null;
|
2021-02-19 21:08:37 +00:00
|
|
|
|
public object attackingPlayer = null;
|
2020-05-17 00:14:00 +00:00
|
|
|
|
public object data = null;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-29 15:11:29 +00:00
|
|
|
|
public static class DamageType
|
|
|
|
|
{
|
|
|
|
|
public static readonly string
|
|
|
|
|
Bullet = "Bullet",
|
2021-01-04 00:28:58 +00:00
|
|
|
|
Explosion = "Explosion",
|
|
|
|
|
Gas = "Gas",
|
|
|
|
|
Flame = "Flame",
|
|
|
|
|
Melee = "Melee";
|
2020-06-29 15:11:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 00:14:00 +00:00
|
|
|
|
public class Damageable : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
[SerializeField] private float m_health = 0f;
|
|
|
|
|
public float Health { get { return m_health; } set { m_health = value; } }
|
|
|
|
|
|
|
|
|
|
[SerializeField] private UnityEvent m_onDamage = new UnityEvent ();
|
2020-06-09 16:34:15 +00:00
|
|
|
|
public UnityEvent OnDamageEvent => m_onDamage;
|
2020-05-17 00:14:00 +00:00
|
|
|
|
|
|
|
|
|
public DamageInfo LastDamageInfo { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Damage (DamageInfo info)
|
|
|
|
|
{
|
|
|
|
|
this.LastDamageInfo = info;
|
2020-05-17 00:17:52 +00:00
|
|
|
|
|
|
|
|
|
F.RunExceptionSafe(() => m_onDamage.Invoke());
|
2020-05-17 00:14:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void HandleDamageByDefault ()
|
|
|
|
|
{
|
|
|
|
|
DamageInfo info = this.LastDamageInfo;
|
|
|
|
|
|
|
|
|
|
this.Health -= info.amount;
|
|
|
|
|
|
|
|
|
|
if (this.Health <= 0f) {
|
|
|
|
|
Destroy (this.gameObject);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-28 14:35:35 +00:00
|
|
|
|
public static void InflictDamageToObjectsInArea(
|
2021-02-19 21:08:37 +00:00
|
|
|
|
Vector3 center,
|
|
|
|
|
float radius,
|
|
|
|
|
float damageAmount,
|
|
|
|
|
AnimationCurve damageOverDistanceCurve,
|
|
|
|
|
string damageType,
|
|
|
|
|
object attacker = null,
|
|
|
|
|
object attackingPlayer = null)
|
2020-06-21 16:21:15 +00:00
|
|
|
|
{
|
2020-06-27 19:55:04 +00:00
|
|
|
|
Collider[] overlappingColliders = Physics.OverlapSphere(center, radius);
|
2020-06-21 16:21:15 +00:00
|
|
|
|
|
2020-06-27 19:55:04 +00:00
|
|
|
|
var damagables = new Dictionary<Damageable, List<Collider>>();
|
2020-06-21 16:21:15 +00:00
|
|
|
|
|
2020-06-27 19:55:04 +00:00
|
|
|
|
foreach (var collider in overlappingColliders)
|
2020-06-21 16:21:15 +00:00
|
|
|
|
{
|
|
|
|
|
var damagable = collider.GetComponentInParent<Damageable>();
|
2020-06-27 19:55:04 +00:00
|
|
|
|
if (damagable != null)
|
2020-06-21 16:21:15 +00:00
|
|
|
|
{
|
2020-06-27 19:55:04 +00:00
|
|
|
|
if (damagables.ContainsKey(damagable))
|
|
|
|
|
{
|
|
|
|
|
damagables[damagable].Add(collider);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
damagables.Add(damagable, new List<Collider>() { collider });
|
|
|
|
|
}
|
2020-06-21 16:21:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-27 19:55:04 +00:00
|
|
|
|
foreach (var pair in damagables)
|
2020-06-21 16:21:15 +00:00
|
|
|
|
{
|
2020-06-27 19:55:04 +00:00
|
|
|
|
Damageable damageable = pair.Key;
|
|
|
|
|
List<Collider> colliders = pair.Value;
|
2020-06-21 16:21:15 +00:00
|
|
|
|
|
2020-06-27 19:55:04 +00:00
|
|
|
|
// find closest point from all colliders
|
2020-06-21 16:21:15 +00:00
|
|
|
|
|
2020-06-27 19:55:04 +00:00
|
|
|
|
float closestPointDistance = float.MaxValue;
|
|
|
|
|
|
2020-07-01 17:25:59 +00:00
|
|
|
|
foreach (var collider in colliders)
|
2020-06-27 19:55:04 +00:00
|
|
|
|
{
|
2020-06-28 18:38:23 +00:00
|
|
|
|
Vector3 closestPointOnCollider = collider.ClosestPointOrBoundsCenter(center);
|
2020-06-27 19:55:04 +00:00
|
|
|
|
float distanceToPointOnCollider = Vector3.Distance(center, closestPointOnCollider);
|
|
|
|
|
|
2020-06-28 21:56:20 +00:00
|
|
|
|
if (distanceToPointOnCollider < closestPointDistance)
|
2020-06-27 19:55:04 +00:00
|
|
|
|
{
|
2020-06-28 21:56:20 +00:00
|
|
|
|
closestPointDistance = distanceToPointOnCollider;
|
2020-06-27 19:55:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// apply damage based on closest distance
|
|
|
|
|
|
|
|
|
|
float distance = closestPointDistance;
|
2020-06-28 14:35:35 +00:00
|
|
|
|
float distanceFactor = damageOverDistanceCurve.Evaluate(Mathf.Clamp01(distance / radius));
|
2020-06-21 16:21:15 +00:00
|
|
|
|
float damageAmountBasedOnDistance = damageAmount * distanceFactor;
|
|
|
|
|
|
2021-02-19 21:08:37 +00:00
|
|
|
|
F.RunExceptionSafe(() => damageable.Damage(new DamageInfo
|
|
|
|
|
{
|
|
|
|
|
amount = damageAmountBasedOnDistance,
|
|
|
|
|
damageType = damageType,
|
|
|
|
|
attacker = attacker,
|
|
|
|
|
attackingPlayer = attackingPlayer,
|
|
|
|
|
}));
|
2020-06-21 16:21:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 00:14:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|