using Content.Server.Body.Systems; using Content.Server.Chemistry.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Robust.Shared.Audio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Body.Components { [RegisterComponent, Access(typeof(BloodstreamSystem), (typeof(ChemistrySystem)))] public sealed class BloodstreamComponent : Component { public static string DefaultChemicalsSolutionName = "chemicals"; public static string DefaultBloodSolutionName = "bloodstream"; public static string DefaultBloodTemporarySolutionName = "bloodstreamTemporary"; public float AccumulatedFrametime = 0.0f; /// /// 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 should be reduced every update interval? /// [DataField("bleedReductionAmount")] public float BleedReductionAmount = 1.0f; /// /// How high can go? /// [DataField("maxBleedAmount")] public float MaxBleedAmount = 20.0f; /// /// What percentage of current blood is necessary to avoid dealing blood loss damage? /// [DataField("bloodlossThreshold")] public float BloodlossThreshold = 0.9f; /// /// The base bloodloss damage to be incurred if below /// [DataField("bloodlossDamage", required: true)] public DamageSpecifier BloodlossDamage = new(); /// /// The base bloodloss damage to be healed if above /// [DataField("bloodlossHealDamage", required: true)] public DamageSpecifier BloodlossHealDamage = new(); /// /// How frequently should this bloodstream update, in seconds? /// [DataField("updateInterval")] public float UpdateInterval = 5.0f; // 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("bloodRefreshAmount")] public float BloodRefreshAmount = 0.3f; /// /// How much blood needs to be in the temporary solution in order to create a puddle? /// [DataField("bleedPuddleThreshold")] public FixedPoint2 BleedPuddleThreshold = 5.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("damageBleedModifiers", customTypeSerializer:typeof(PrototypeIdSerializer))] public string DamageBleedModifiers = "BloodlossHuman"; /// /// The sound to be played when a weapon instantly deals blood loss damage. /// [DataField("instantBloodSound")] public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood"); /// /// The sound to be played when some damage actually heals bleeding rather than starting it. /// [DataField("bloodHealedSound")] public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg"); // TODO probably damage bleed thresholds. /// /// Max volume of internal chemical solution storage /// [DataField("chemicalMaxVolume")] public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250); /// /// Max volume of internal blood storage, /// and starting level of blood. /// [DataField("bloodMaxVolume")] 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("bloodReagent")] public string BloodReagent = "Blood"; /// /// Internal solution for reagent storage /// [ViewVariables(VVAccess.ReadWrite)] [Access(typeof(BloodstreamSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends public Solution ChemicalSolution = default!; /// /// Internal solution for blood storage /// [ViewVariables(VVAccess.ReadWrite)] public Solution BloodSolution = default!; /// /// 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(VVAccess.ReadWrite)] public Solution BloodTemporarySolution = default!; } }