diff --git a/Content.Server/Cloning/CloningSystem.Subscriptions.cs b/Content.Server/Cloning/CloningSystem.Subscriptions.cs index 373ce5f8e1..cb1c8593f8 100644 --- a/Content.Server/Cloning/CloningSystem.Subscriptions.cs +++ b/Content.Server/Cloning/CloningSystem.Subscriptions.cs @@ -1,5 +1,7 @@ using Content.Server.Forensics; using Content.Server.Speech.EntitySystems; +using Content.Shared.Body.Components; +using Content.Shared.Body.Systems; using Content.Shared.Cloning.Events; using Content.Shared.Clothing.Components; using Content.Shared.Clothing.EntitySystems; @@ -38,6 +40,7 @@ public sealed partial class CloningSystem [Dependency] private MovementSpeedModifierSystem _movementSpeedModifier = default!; [Dependency] private SharedChameleonClothingSystem _chameleonClothing = default!; [Dependency] private PullingSystem _pulling = default!; + [Dependency] private SharedBloodstreamSystem _bloodstream = default!; public override void Initialize() { @@ -62,6 +65,7 @@ public sealed partial class CloningSystem SubscribeLocalEvent(OnCloneInventory); SubscribeLocalEvent(OnCloneMovementSpeedModifier); SubscribeLocalEvent(OnClonePuller); + SubscribeLocalEvent(OnCloneBloodstream); } private void OnCloneItemStack(Entity ent, ref CloningItemEvent args) @@ -149,4 +153,12 @@ public sealed partial class CloningSystem _pulling.CopyPullerComponent(ent.AsNullable(), args.CloneUid); } + + private void OnCloneBloodstream(Entity ent, ref CloningEvent args) + { + if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name)) + return; + + _bloodstream.CopyComponent(ent.AsNullable(), args.CloneUid); + } } diff --git a/Content.Shared/Body/Components/BloodstreamComponent.cs b/Content.Shared/Body/Components/BloodstreamComponent.cs index dca7d58be7..73f042f234 100644 --- a/Content.Shared/Body/Components/BloodstreamComponent.cs +++ b/Content.Shared/Body/Components/BloodstreamComponent.cs @@ -126,14 +126,14 @@ public sealed partial class BloodstreamComponent : Component /// /// The sound to be played when some damage actually heals bleeding rather than starting it. /// - [DataField] + [DataField, AutoNetworkedField] 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] + [DataField, AutoNetworkedField] public float BloodHealedSoundThreshold = -0.1f; // TODO probably damage bleed thresholds. diff --git a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs index 968a62286c..2ea349a622 100644 --- a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs +++ b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Fluids; using Content.Shared.Forensics.Components; using Content.Shared.Gibbing; using Content.Shared.HealthExaminable; +using Content.Shared.Metabolism; using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Random.Helpers; @@ -39,6 +40,7 @@ public abstract partial class SharedBloodstreamSystem : EntitySystem [Dependency] private AlertsSystem _alertsSystem = default!; [Dependency] private MobStateSystem _mobStateSystem = default!; [Dependency] private DamageableSystem _damageableSystem = default!; + [Dependency] private MetabolizerSystem _metabolizer = default!; public override void Initialize() { @@ -614,4 +616,43 @@ public abstract partial class SharedBloodstreamSystem : EntitySystem bloodData.Add(dnaData); return bloodData; } + + /// + /// Copies the values in of one entity to another. + /// If the component isn't on the target entity, it is added. + /// + /// The entity who's component to use. + /// The target to clone the component onto. + public void CopyComponent(Entity source, EntityUid target) + { + if (!Resolve(source, ref source.Comp)) + return; + + // We don't create the component before adding it here. + // This is because it causes the initialization to get a bit fucky together with ChangeBloodReagent. + // The reagents won't actually change unless we do it this way. + // The DNA and stuff is updated by themselves anyway. + // BleedAmount is excluded on purpose. There is no point in cloning how much someone is bleeding at the moment. + var cloneComp = EnsureComp(target); + cloneComp.UpdateInterval = source.Comp.UpdateInterval; + cloneComp.UpdateIntervalMultiplier = source.Comp.UpdateIntervalMultiplier; + cloneComp.BleedReductionAmount = source.Comp.BleedReductionAmount; + cloneComp.MaxBleedAmount = source.Comp.MaxBleedAmount; + cloneComp.BloodlossThreshold = source.Comp.BloodlossThreshold; + cloneComp.BloodlossDamage = new DamageSpecifier(source.Comp.BloodlossDamage); + cloneComp.BloodlossHealDamage = new DamageSpecifier(source.Comp.BloodlossHealDamage); + cloneComp.BloodRefreshAmount = source.Comp.BloodRefreshAmount; + cloneComp.BleedPuddleThreshold = source.Comp.BleedPuddleThreshold; + cloneComp.DamageBleedModifiers = source.Comp.DamageBleedModifiers; + cloneComp.MaxVolumeModifier = source.Comp.MaxVolumeModifier; + cloneComp.InstantBloodSound = source.Comp.InstantBloodSound; + cloneComp.BloodHealedSound = source.Comp.BloodHealedSound; + cloneComp.BloodHealedSoundThreshold = source.Comp.BloodHealedSoundThreshold; + + Dirty(target, cloneComp); + + // ChangeBloodReagents dirties the values it changes by itself. + ChangeBloodReagents((target, cloneComp), source.Comp.BloodReferenceSolution); + _metabolizer.UpdateMetabolicMultiplier(target); + } } diff --git a/Resources/Prototypes/Entities/Mobs/Player/clone.yml b/Resources/Prototypes/Entities/Mobs/Player/clone.yml index 4fdd0a8964..8e26fe9cdb 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/clone.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/clone.yml @@ -154,6 +154,7 @@ - Sericulture # arachnids - MovementSpeedModifier # moths when weightless - JumpAbility # vulp leaping + - Bloodstream # blood reagents copyInternalStorage: false copyImplants: false raiseEntityRenamedEvent: false