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;
}
}