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