#nullable enable using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.EntitySystems; using Robust.Shared.Interfaces.GameObjects; namespace Content.Shared.GameObjects.Components.Damage { public interface IDamageableComponent : IComponent, IExAct { /// /// Called when the entity's values change. /// Of note is that a "deal 0 damage" call will still trigger this event /// (including both damage negated by resistance or simply inputting 0 as /// the amount of damage to deal). /// event Action HealthChangedEvent; /// /// List of all DamageStates that /// can be. /// List SupportedDamageStates { get; } /// /// The currently representing this component. /// DamageState CurrentDamageState { get; } /// /// Sum of all damages taken. /// int TotalDamage { get; } /// /// The amount of damage mapped by . /// IReadOnlyDictionary DamageClasses { get; } /// /// The amount of damage mapped by . /// IReadOnlyDictionary DamageTypes { get; } /// /// Gets the amount of damage of a type. /// /// The type to get the damage of. /// The amount of damage of that type. /// /// True if the given is supported, false otherwise. /// bool TryGetDamage(DamageType type, [NotNullWhen(true)] out int damage); /// /// Changes the specified , applying /// resistance values only if it is damage. /// /// Type of damage being changed. /// /// Amount of damage being received (positive for damage, negative for heals). /// /// /// Whether or not to ignore resistances. /// Healing always ignores resistances, regardless of this input. /// /// /// The entity that dealt or healed the damage, if any. /// /// /// Extra parameters that some components may require, such as a specific limb to target. /// /// /// False if the given type is not supported or improper /// were provided; true otherwise. /// bool ChangeDamage(DamageType type, int amount, bool ignoreResistances, IEntity? source = null, HealthChangeParams? extraParams = null); /// /// Changes the specified , applying /// resistance values only if it is damage. /// Spreads amount evenly between the s /// represented by that class. /// /// Class of damage being changed. /// /// Amount of damage being received (positive for damage, negative for heals). /// /// /// Whether to ignore resistances. /// Healing always ignores resistances, regardless of this input. /// /// Entity that dealt or healed the damage, if any. /// /// Extra parameters that some components may require, /// such as a specific limb to target. /// /// /// Returns false if the given class is not supported or improper /// were provided; true otherwise. /// bool ChangeDamage(DamageClass @class, int amount, bool ignoreResistances, IEntity? source = null, HealthChangeParams? extraParams = null); /// /// Forcefully sets the specified to the given /// value, ignoring resistance values. /// /// Type of damage being changed. /// New damage value to be set. /// Entity that set the new damage value. /// /// Extra parameters that some components may require, /// such as a specific limb to target. /// /// /// Returns false if the given type is not supported or improper /// were provided; true otherwise. /// bool SetDamage(DamageType type, int newValue, IEntity? source = null, HealthChangeParams? extraParams = null); /// /// Sets all damage values to zero. /// void Heal(); /// /// Invokes the HealthChangedEvent with the current values of health. /// void ForceHealthChangedEvent(); void IExAct.OnExplosion(ExplosionEventArgs eventArgs) { var damage = eventArgs.Severity switch { ExplosionSeverity.Light => 20, ExplosionSeverity.Heavy => 60, ExplosionSeverity.Destruction => 250, _ => throw new ArgumentOutOfRangeException() }; ChangeDamage(DamageType.Piercing, damage, false, null); ChangeDamage(DamageType.Heat, damage, false, null); } } /// /// Data class with information on how to damage a /// . /// While not necessary to damage for all instances, classes such as /// may require it for extra data /// (such as selecting which limb to target). /// public class HealthChangeParams : EventArgs { } /// /// Data class with information on how the /// values of a have changed. /// public class HealthChangedEventArgs : EventArgs { /// /// Reference to the that invoked the event. /// public readonly IDamageableComponent Damageable; /// /// List containing data on each that was changed. /// public readonly List Data; public HealthChangedEventArgs(IDamageableComponent damageable, List data) { Damageable = damageable; Data = data; } public HealthChangedEventArgs(IDamageableComponent damageable, DamageType type, int newValue, int delta) { Damageable = damageable; var datum = new HealthChangeData(type, newValue, delta); var data = new List {datum}; Data = data; } } /// /// Data class with information on how the value of a /// single has changed. /// public struct HealthChangeData { /// /// Type of damage that changed. /// public DamageType Type; /// /// The new current value for that damage. /// public int NewValue; /// /// How much the health value changed from its last value (negative is heals, positive is damage). /// public int Delta; public HealthChangeData(DamageType type, int newValue, int delta) { Type = type; NewValue = newValue; Delta = delta; } } }