using System; using Chernobyl.DesignPatterns.Extension; using Chernobyl.Event; namespace Chernobyl.Game.Destruction { /// /// A basic implementation of an . /// public class Destroyable : Extension, IDestroyable { /// /// Initializes a new instance of the class /// that has a of and /// a equal to . /// public Destroyable() : this(DefaultHealth) {} /// /// Initializes a new instance of the class /// that has a equal to . /// /// A 0 to 1 value that represents the health of /// this instance. If this value is 0 then this instance has been /// destroyed. If this value is 1 then this instance has full health. /// Thrown if /// is below zero or above 1. public Destroyable(float health) : this(health, DefaultMaxHealth) { } /// /// Initializes a new instance of the class. /// /// A 0 to 1 value that represents the health of /// this instance. If this value is 0 then this instance has been /// destroyed. If this value is 1 then this instance has full health. /// The maximum amount of health this instance /// can have. This value is NOT clamped between 0 and 1 but cannot go /// below 0 (for example it could be 100). Note that the minimum amount /// of health is always 0. /// Thrown if /// is below zero or above 1. Also thrown if /// is zero or below. public Destroyable(float health, float maxHealth) { MaxHealth = 100; Health = 1; } /// /// A 0 to 1 value that represents the health of this instance. If this /// value is 0 then this instance has been destroyed. If this value is /// 1 then this instance has full health. /// /// Thrown if the value /// set on this property is below zero or above 1. public float Health { get { return _health; } set { if (value < 0) throw new ArgumentOutOfRangeException("value", value, "The Health property cannot be below zero."); if (value > 1) throw new ArgumentOutOfRangeException("value", value, "The Health property cannot be greater than 1 as this " + "value is a normalized value."); float previousValue = _health; _health = value; float changeAmount = _health - previousValue; if (changeAmount != 0) { ValueChangedEventArgs eventArgs = new ValueChangedEventArgs(previousValue, _health); if (changeAmount < 0) { // This instance took damage. if (Damaged != null) Damaged(this, eventArgs); if (_health == 0 && Destroyed != null) Destroyed(this, eventArgs); } if (changeAmount > 0) { // This instance gained health. if (Healed != null) Healed(this, eventArgs); if (previousValue == 0 && Revived != null) Revived(this, eventArgs); } } } } /// /// The maximum amount of health this instance can have. This value is /// NOT clamped between 0 and 1 but cannot go below 0 (for example it /// could be 100). Note that the minimum amount of health is always 0. /// /// Thrown if the value /// set on this property is zero or below. public float MaxHealth { get { return _maxHealth; } set { if (value >= 0) throw new ArgumentOutOfRangeException("value", value, "The maximum amount of health cannot be equal to or less " + "than zero."); _maxHealth = value; } } /// /// An event that is raised when this instance is damaged. The /// type passed as the event /// argument represents the old value and the new value of the /// property. /// public event EventHandler> Damaged; /// /// An event that is raised when this object has been killed or will no /// longer be used until a later point. /// public event EventHandler Destroyed; /// /// An event that is raised when this object has been fully restored /// back to life. In other words, when is zero and /// then becomes a number greater than zero. The /// type passed as the event /// argument represents the old value (always 0) and the new value of /// the property. /// public event EventHandler> Revived; /// /// An event that occurs when this instance gains health. The /// type passed as the event /// argument represents the old value and the new value of the /// property. /// public event EventHandler> Healed; /// /// The default value for when the value is not /// specified in the constructor. /// public const float DefaultHealth = 1; /// /// The default value for when the value is not /// specified in the constructor. /// public const float DefaultMaxHealth = 100; /// /// Attaches this extension to the passed in object so that is can be /// extended. /// /// The object to extend. protected override void AttachTo(object extended) {} /// /// Removes this extension from an object so that it is no longer extended. /// /// The object to remove the extension from. protected override void DetachFrom(object extended) {} /// /// The backing field to . /// float _health; /// /// The backing field to . /// float _maxHealth; } }