using Content.Server.Body.Systems; using Content.Server.Chemistry.EntitySystems; using Content.Shared.Alert; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Server.Body.Components { [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem))] public sealed partial class BloodstreamComponent : Component { public static string DefaultChemicalsSolutionName = "chemicals"; public static string DefaultBloodSolutionName = "bloodstream"; public static string DefaultBloodTemporarySolutionName = "bloodstreamTemporary"; /// /// The next time that blood level will be updated and bloodloss damage dealt. /// [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan NextUpdate; /// /// The interval at which this component updates. /// [DataField] public TimeSpan UpdateInterval = TimeSpan.FromSeconds(3); /// /// How much is this entity currently bleeding? /// Higher numbers mean more blood lost every tick. /// /// Goes down slowly over time, and items like bandages /// or clotting reagents can lower bleeding. /// /// /// This generally corresponds to an amount of damage and can't go above 100. /// [ViewVariables(VVAccess.ReadWrite)] public float BleedAmount; /// /// How much should bleeding be reduced every update interval? /// [DataField] public float BleedReductionAmount = 0.33f; /// /// How high can go? /// [DataField] public float MaxBleedAmount = 10.0f; /// /// What percentage of current blood is necessary to avoid dealing blood loss damage? /// [DataField] public float BloodlossThreshold = 0.9f; /// /// The base bloodloss damage to be incurred if below /// The default values are defined per mob/species in YML. /// [DataField(required: true)] public DamageSpecifier BloodlossDamage = new(); /// /// The base bloodloss damage to be healed if above /// The default values are defined per mob/species in YML. /// [DataField(required: true)] public DamageSpecifier BloodlossHealDamage = new(); // TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth. /// /// How much reagent of blood should be restored each update interval? /// [DataField] public FixedPoint2 BloodRefreshAmount = 1.0f; /// /// How much blood needs to be in the temporary solution in order to create a puddle? /// [DataField] public FixedPoint2 BleedPuddleThreshold = 1.0f; /// /// A modifier set prototype ID corresponding to how damage should be modified /// before taking it into account for bloodloss. /// /// /// For example, piercing damage is increased while poison damage is nullified entirely. /// [DataField] public ProtoId DamageBleedModifiers = "BloodlossHuman"; /// /// The sound to be played when a weapon instantly deals blood loss damage. /// [DataField] public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood"); /// /// The sound to be played when some damage actually heals bleeding rather than starting it. /// [DataField] public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); /// /// The minimum amount damage reduction needed to play the healing sound/popup. /// This prevents tiny amounts of heat damage from spamming the sound, e.g. spacing. /// [DataField] public float BloodHealedSoundThreshold = -0.1f; // TODO probably damage bleed thresholds. /// /// Max volume of internal chemical solution storage /// [DataField] public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250); /// /// Max volume of internal blood storage, /// and starting level of blood. /// [DataField] public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300); /// /// Which reagent is considered this entities 'blood'? /// /// /// Slime-people might use slime as their blood or something like that. /// [DataField] public ProtoId BloodReagent = "Blood"; /// Name/Key that is indexed by. [DataField] public string BloodSolutionName = DefaultBloodSolutionName; /// Name/Key that is indexed by. [DataField] public string ChemicalSolutionName = DefaultChemicalsSolutionName; /// Name/Key that is indexed by. [DataField] public string BloodTemporarySolutionName = DefaultBloodTemporarySolutionName; /// /// Internal solution for blood storage /// [ViewVariables] public Entity? BloodSolution; /// /// Internal solution for reagent storage /// [ViewVariables] public Entity? ChemicalSolution; /// /// Temporary blood solution. /// When blood is lost, it goes to this solution, and when this /// solution hits a certain cap, the blood is actually spilled as a puddle. /// [ViewVariables] public Entity? TemporarySolution; /// /// Variable that stores the amount of status time added by having a low blood level. /// [ViewVariables(VVAccess.ReadWrite)] public TimeSpan StatusTime; [DataField] public ProtoId BleedingAlert = "Bleed"; } }