GibTreaty

Health Script

Feb 15th, 2015
720
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.95 KB | None | 0 0
  1. using UnityEngine;
  2. using UnityEngine.Events;
  3. using System;
  4.  
  5. /// <summary>
  6. /// Manages your health and sends messages when certain health events happen
  7. ///
  8. /// - To send a message to a GameObject you can use SendMessage or call them directly -
  9. ///
  10. /// targetGameObject.SendMessage("Heal", new HealthEvent(gameObject, amount));
  11. /// targetGameObject.SendMessage("Damage", new HealthEvent(gameObject, amount));
  12. ///
  13. /// targetHealth.Heal(new HealthEvent(gameObject, amount));
  14. /// targetHealth.Damage(new HealthEvent(gameObject, amount));
  15. ///
  16. ///
  17. /// - These functions you can add to your script to receive the events -
  18. ///
  19. /// void OnHealed(HealthEvent event) - Triggered on the object whose health has gone up
  20. /// void OnCausedHeal(HealthEvent event) - Triggered on the object who has caused another object's health to go down
  21. ///
  22. /// void OnDamaged(HealthEvent event) - Triggered on the object whose health has gone down
  23. /// void OnCausedDamage(HealthEvent event) - Triggered on the object who has caused another object's health to go up
  24. ///
  25. /// void OnDeath(HealthEvent event) - Triggered on the object whose health has gone on or below zero
  26. /// void OnCausedDeath(HealthEvent event) - Triggered on the object who has caused another object's health to be at or below zero
  27. /// </summary>
  28. [AddComponentMenu("Health/Health")]
  29. public class Health : MonoBehaviour, IStat {
  30.  
  31. #if UNITY_EDITOR
  32.     float editor_value;
  33. #endif
  34.     [SerializeField]
  35.     float _value = 100;
  36.     public float Value {
  37.         get { return _value; }
  38.         set {
  39.             if(disableHealthChange) return;
  40.  
  41.             float oldValue = _value;
  42.  
  43.             _value = capHealth ? Mathf.Clamp(value, 0, _maxValue) : value;
  44.  
  45.             if(!Mathf.Approximately(_value, oldValue))
  46.                 if(OnChangedHealth != null) OnChangedHealth.Invoke(_value);
  47.         }
  48.     }
  49.  
  50. #if UNITY_EDITOR
  51.     float editor_maxValue;
  52. #endif
  53.     [SerializeField]
  54.     float _maxValue = 100;
  55.     public float MaxValue {
  56.         get { return _maxValue; }
  57.         set {
  58.             float oldValue = _maxValue;
  59.  
  60.             _maxValue = Mathf.Max(value, 0);
  61.  
  62.             if(!Mathf.Approximately(_maxValue, oldValue)) {
  63.                 if(OnChangedMaxHealth != null) OnChangedMaxHealth.Invoke(_maxValue);
  64.  
  65.                 if(capHealth)
  66.                     Value = Mathf.Clamp(Value, 0, _maxValue);
  67.             }
  68.         }
  69.     }
  70.  
  71.     public float NormalizedValue {
  72.         get { return Mathf.InverseLerp(0, MaxValue, Value); }
  73.         set { Value = Mathf.Lerp(0, MaxValue, value); }
  74.     }
  75.  
  76.     [Tooltip("Don't let the health go lower than 0 or higher than the max health")]
  77.     public bool capHealth = true;
  78.  
  79.     /// <summary>
  80.     /// Disables health being changed from the Heal, Damage and ChangeHealth functions
  81.     /// </summary>
  82.     public bool disableHealthChange = false;
  83.  
  84.     [SerializeField, Tooltip("Disable damage")]
  85.     bool _invincible;
  86.     public bool Invincible {
  87.         get { return _invincible; }
  88.         set { _invincible = value; }
  89.     }
  90.  
  91.     [SerializeField, Tooltip("Disable healing")]
  92.     bool _incurable;
  93.     public bool Incurable {
  94.         get { return _incurable; }
  95.         set { _incurable = value; }
  96.     }
  97.  
  98.     public HealthChangeEvent OnChangedHealth;
  99.     public HealthChangeEvent OnChangedMaxHealth;
  100.  
  101.     [Header("Received Health Events")]
  102.     [Tooltip("Health went up")]
  103.     public UnityHealthEvent OnHealed;
  104.     [Tooltip("Health is at or above max")]
  105.     public UnityHealthEvent OnRestored;
  106.     [Tooltip("Health went down")]
  107.     public UnityHealthEvent OnDamaged;
  108.     [Tooltip("Health is at or below zero")]
  109.     public UnityHealthEvent OnDeath;
  110.  
  111.     [Header("Caused Health Events")]
  112.     public UnityHealthEvent OnCausedHeal;
  113.     public UnityHealthEvent OnCausedRestoration;
  114.     public UnityHealthEvent OnCausedDamage;
  115.     public UnityHealthEvent OnCausedDeath;
  116.  
  117.     protected virtual void Awake() {
  118.         if(OnChangedHealth != null) OnChangedHealth.Invoke(Value);
  119.         if(OnChangedMaxHealth != null) OnChangedMaxHealth.Invoke(MaxValue);
  120.     }
  121.  
  122.     public float ChangeHealth(HealthEvent healthEvent) {
  123.         if(!disableHealthChange) {
  124.             float newHealth = Mathf.Clamp(Value + healthEvent.amount, 0, MaxValue);
  125.             float healthChange = newHealth - Value;
  126.  
  127.             if(healthChange > 0) {
  128.                 if(Incurable) return Value;
  129.             }
  130.             else if(healthChange < 0) {
  131.                 if(Invincible) return Value;
  132.             }
  133.             else return Value;
  134.  
  135.             Value = newHealth;
  136.  
  137.             HealthEvent received = new HealthEvent(healthEvent.originGameObject, gameObject, healthChange, healthEvent.description);
  138.             HealthEvent caused = new HealthEvent(gameObject, healthEvent.originGameObject, healthChange, healthEvent.description);
  139.  
  140.             if(healthChange > 0) { //Healed
  141.                 if(OnHealed != null) OnHealed.Invoke(received);
  142.  
  143.                 if(healthEvent.originGameObject) {
  144.                     Health causedEvent = healthEvent.originGameObject.GetComponentInParent<Health>();
  145.  
  146.                     if(causedEvent && causedEvent.OnCausedHeal != null)
  147.                         causedEvent.OnCausedHeal.Invoke(caused);
  148.                 }
  149.             }
  150.             else if(healthChange < 0) { //Damaged
  151.                 if(OnDamaged != null) OnDamaged.Invoke(received);
  152.  
  153.                 if(healthEvent.originGameObject) {
  154.                     Health causedEvent = healthEvent.originGameObject.GetComponentInParent<Health>();
  155.  
  156.                     if(causedEvent && causedEvent.OnCausedDamage != null)
  157.                         causedEvent.OnCausedDamage.Invoke(caused);
  158.                 }
  159.             }
  160.  
  161.             if(Value <= 0) {
  162.                 if(healthChange < 0) { //Death
  163.                     if(OnDeath != null) OnDeath.Invoke(received);
  164.  
  165.                     if(healthEvent.originGameObject) {
  166.                         Health causedEvent = healthEvent.originGameObject.GetComponentInParent<Health>();
  167.  
  168.                         if(causedEvent && causedEvent.OnCausedDeath != null)
  169.                             causedEvent.OnCausedDeath.Invoke(caused);
  170.                     }
  171.                 }
  172.             }
  173.             else if(Value >= MaxValue) { //Restored
  174.                 if(healthChange > 0) {
  175.                     if(OnRestored != null) OnRestored.Invoke(received);
  176.  
  177.                     if(healthEvent.originGameObject) {
  178.                         Health causedEvent = healthEvent.originGameObject.GetComponentInParent<Health>();
  179.  
  180.                         if(causedEvent && causedEvent.OnCausedRestoration != null)
  181.                             causedEvent.OnCausedRestoration.Invoke(caused);
  182.                     }
  183.                 }
  184.             }
  185.         }
  186.  
  187.         return Value;
  188.     }
  189.  
  190.     /// <summary>
  191.     /// Subtracts health
  192.     /// </summary>
  193.     /// <param name="healthEvent"></param>
  194.     public bool Damage(HealthEvent healthEvent) {
  195.         if(!disableHealthChange) {
  196.             //healthEvent.amount = -Mathf.Abs(healthEvent.amount);
  197.             if(healthEvent.amount > 0) healthEvent.amount = -healthEvent.amount;
  198.  
  199.             return Value > ChangeHealth(healthEvent);
  200.         }
  201.  
  202.         return false;
  203.     }
  204.  
  205.     /// <summary>
  206.     /// Adds health
  207.     /// </summary>
  208.     /// <param name="healthEvent"></param>
  209.     public bool Heal(HealthEvent healthEvent) {
  210.         if(!disableHealthChange) {
  211.             //healthEvent.amount = Mathf.Abs(healthEvent.amount);
  212.             if(healthEvent.amount < 0) healthEvent.amount = -healthEvent.amount;
  213.  
  214.             return Value < ChangeHealth(healthEvent);
  215.         }
  216.  
  217.         return false;
  218.     }
  219.  
  220.     /// <summary>
  221.     /// Resets health
  222.     /// </summary>
  223.     public virtual void Reset() {
  224.         //ChangeHealth(new HealthEvent(null, MaxValue));
  225.         Value = MaxValue;
  226.     }
  227.  
  228.     void OnValidate() {
  229. #if UNITY_EDITOR
  230.         if(editor_value != Value)
  231.             if(OnChangedHealth != null) OnChangedHealth.Invoke(Value);
  232.  
  233.         if(editor_maxValue != MaxValue)
  234.             if(OnChangedMaxHealth != null) OnChangedMaxHealth.Invoke(MaxValue);
  235. #endif
  236.  
  237.         Value = _value;
  238.         MaxValue = _maxValue;
  239.  
  240. #if UNITY_EDITOR
  241.         editor_value = Value;
  242.         editor_maxValue = MaxValue;
  243. #endif
  244.     }
  245.  
  246.     [Serializable]
  247.     public class HealthChangeEvent : UnityEvent<float> { }
  248.     [Serializable]
  249.     public class UnityHealthEvent : UnityEvent<HealthEvent> { }
  250. }
  251.  
  252. public struct HealthEvent {
  253.     /// <summary>
  254.     /// The GameObject that caused the health event to happen
  255.     /// </summary>
  256.     public GameObject originGameObject;
  257.  
  258.     /// <summary>
  259.     /// The GameObject that was effected by this health event
  260.     /// </summary>
  261.     public GameObject targetGameObject;
  262.  
  263.     /// <summary>
  264.     /// The amount of health to change
  265.     /// </summary>
  266.     public float amount;
  267.  
  268.     /// <summary>
  269.     /// Describes the nature of the event
  270.     /// </summary>
  271.     public string description;
  272.  
  273.     public HealthEvent(GameObject originGameObject, float amount) {
  274.         this.originGameObject = originGameObject;
  275.         targetGameObject = null;
  276.         this.amount = amount;
  277.         description = "";
  278.     }
  279.     public HealthEvent(GameObject originGameObject, float amount, string description) {
  280.         this.originGameObject = originGameObject;
  281.         targetGameObject = null;
  282.         this.amount = amount;
  283.         this.description = description;
  284.     }
  285.  
  286.     public HealthEvent(GameObject originGameObject, GameObject targetGameObject, float amount) {
  287.         this.originGameObject = originGameObject;
  288.         this.targetGameObject = targetGameObject;
  289.         this.amount = amount;
  290.         description = "";
  291.     }
  292.     public HealthEvent(GameObject originGameObject, GameObject targetGameObject, float amount, string description) {
  293.         this.originGameObject = originGameObject;
  294.         this.targetGameObject = targetGameObject;
  295.         this.amount = amount;
  296.         this.description = description;
  297.     }
  298.  
  299.     public override string ToString() {
  300.         string message = "";
  301.  
  302.         message += "Origin(" + (originGameObject ? originGameObject.name : "null") + ")";
  303.         message += "\nEffected(" + (targetGameObject ? targetGameObject.name : "null") + ")";
  304.         message += "\nAmount(" + amount + ")";
  305.  
  306.         if(!string.IsNullOrEmpty(description))
  307.             message += "\n" + description;
  308.  
  309.         return message;
  310.     }
  311. }
Advertisement
Add Comment
Please, Sign In to add comment