using System; using System.Collections.Generic; using Content.Shared.Acts; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Content.Shared.Radiation; using Robust.Shared.Analyzers; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.ViewVariables; namespace Content.Shared.Damage { /// /// Component that allows entities to take damage. /// /// /// The supported damage types are specified using a s. DamageContainers /// may also have resistances to certain damage types, defined via a . /// [RegisterComponent] [NetworkedComponent()] [Friend(typeof(DamageableSystem))] public class DamageableComponent : Component, IRadiationAct, IExAct { public override string Name => "Damageable"; /// /// This specifies what damage types are supported by this component. /// If null, all damage types will be supported. /// [DataField("damageContainer", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? DamageContainerID; /// /// This will be applied to any damage that is dealt to this container, /// unless the damage explicitly ignores resistances. /// /// /// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here /// to reduce duplication. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("damageModifierSet", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? DamageModifierSetId; /// /// All the damage information is stored in this . /// /// /// If this data-field is specified, this allows damageable components to be initialized with non-zero damage. /// [DataField("damage")] [ViewVariables(VVAccess.ReadWrite)] public DamageSpecifier Damage = new(); /// /// Damage, indexed by ID keys. /// /// /// Groups which have no members that are supported by this component will not be present in this /// dictionary. /// [ViewVariables] public Dictionary DamagePerGroup = new(); /// /// The sum of all damages in the DamageableComponent. /// [ViewVariables] public FixedPoint2 TotalDamage; // Really these shouldn't be here. OnExplosion() and RadiationAct() should be handled elsewhere. [ViewVariables] [DataField("radiationDamageTypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List RadiationDamageTypeIDs = new() {"Radiation"}; [ViewVariables] [DataField("explosionDamageTypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List ExplosionDamageTypeIDs = new() { "Piercing", "Heat" }; // TODO RADIATION Remove this. void IRadiationAct.RadiationAct(float frameTime, SharedRadiationPulseComponent radiation) { var damageValue = FixedPoint2.New(MathF.Max((frameTime * radiation.RadsPerSecond), 1)); // Radiation should really just be a damage group instead of a list of types. DamageSpecifier damage = new(); foreach (var typeID in RadiationDamageTypeIDs) { damage.DamageDict.Add(typeID, damageValue); } EntitySystem.Get().TryChangeDamage(Owner, damage); } // TODO EXPLOSION Remove this. void IExAct.OnExplosion(ExplosionEventArgs eventArgs) { var damageValue = eventArgs.Severity switch { ExplosionSeverity.Light => FixedPoint2.New(20), ExplosionSeverity.Heavy => FixedPoint2.New(60), ExplosionSeverity.Destruction => FixedPoint2.New(250), _ => throw new ArgumentOutOfRangeException() }; // Explosion should really just be a damage group instead of a list of types. DamageSpecifier damage = new(); foreach (var typeID in ExplosionDamageTypeIDs) { damage.DamageDict.Add(typeID, damageValue); } EntitySystem.Get().TryChangeDamage(Owner, damage); } } [Serializable, NetSerializable] public class DamageableComponentState : ComponentState { public readonly Dictionary DamageDict; public readonly string? ModifierSetId; public DamageableComponentState( Dictionary damageDict, string? modifierSetId) { DamageDict = damageDict; ModifierSetId = modifierSetId; } } }