diff --git a/Content.Server/Chemistry/Components/HyposprayComponent.cs b/Content.Server/Chemistry/Components/HyposprayComponent.cs index 92d8bb4a99..9463521347 100644 --- a/Content.Server/Chemistry/Components/HyposprayComponent.cs +++ b/Content.Server/Chemistry/Components/HyposprayComponent.cs @@ -1,17 +1,7 @@ -using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.EntitySystems; -using Content.Server.Interaction.Components; using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; -using Content.Shared.IdentityManagement; -using Content.Shared.MobState.Components; -using Content.Shared.Popups; using Robust.Shared.Audio; -using Robust.Shared.Player; -using System.Diagnostics.CodeAnalysis; -using Content.Server.Interaction; -using Content.Server.Weapons.Melee; namespace Content.Server.Chemistry.Components { @@ -29,97 +19,7 @@ namespace Content.Server.Chemistry.Components public FixedPoint2 TransferAmount { get; set; } = FixedPoint2.New(5); [DataField("injectSound")] - private SoundSpecifier _injectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg"); - - protected override void Initialize() - { - base.Initialize(); - - Dirty(); - } - - public bool TryDoInject(EntityUid? target, EntityUid user) - { - if (!EligibleEntity(target, _entMan)) - return false; - - string? msgFormat = null; - - if (target == user) - { - msgFormat = "hypospray-component-inject-self-message"; - } - else if (EligibleEntity(user, _entMan) && _entMan.EntitySysManager.GetEntitySystem().TryRollClumsy(user, ClumsyFailChance)) - { - msgFormat = "hypospray-component-inject-self-clumsy-message"; - target = user; - } - - var solutionsSys = EntitySystem.Get(); - solutionsSys.TryGetSolution(Owner, SolutionName, out var hypoSpraySolution); - - if (hypoSpraySolution == null || hypoSpraySolution.CurrentVolume == 0) - { - user.PopupMessageCursor(Loc.GetString("hypospray-component-empty-message")); - return true; - } - - if (!solutionsSys.TryGetInjectableSolution(target.Value, out var targetSolution)) - { - user.PopupMessage(user, - Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan)))); - return false; - } - - user.PopupMessage(Loc.GetString(msgFormat ?? "hypospray-component-inject-other-message", - ("other", target))); - if (target != user) - { - target.Value.PopupMessage(Loc.GetString("hypospray-component-feel-prick-message")); - var meleeSys = EntitySystem.Get(); - var angle = Angle.FromWorldVec(_entMan.GetComponent(target.Value).WorldPosition - _entMan.GetComponent(user).WorldPosition); - // TODO: This should just be using melee attacks... - // meleeSys.SendLunge(angle, user); - } - - SoundSystem.Play(_injectSound.GetSound(), Filter.Pvs(user), user); - - // Get transfer amount. May be smaller than _transferAmount if not enough room - var realTransferAmount = FixedPoint2.Min(TransferAmount, targetSolution.AvailableVolume); - - if (realTransferAmount <= 0) - { - user.PopupMessage(user, - Loc.GetString("hypospray-component-transfer-already-full-message", - ("owner", target))); - return true; - } - - // Move units from attackSolution to targetSolution - var removedSolution = - EntitySystem.Get() - .SplitSolution(Owner, hypoSpraySolution, realTransferAmount); - - if (!targetSolution.CanAddSolution(removedSolution)) - { - return true; - } - - removedSolution.DoEntityReaction(target.Value, ReactionMethod.Injection); - - EntitySystem.Get().TryAddSolution(target.Value, targetSolution, removedSolution); - - static bool EligibleEntity([NotNullWhen(true)] EntityUid? entity, IEntityManager entMan) - { - // TODO: Does checking for BodyComponent make sense as a "can be hypospray'd" tag? - // In SS13 the hypospray ONLY works on mobs, NOT beakers or anything else. - - return entMan.HasComponent(entity) - && entMan.HasComponent(entity); - } - - return true; - } + public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg"); public override ComponentState GetComponentState() { diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs index 191d8249f5..f4efbf9d47 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs @@ -1,8 +1,10 @@ using Content.Server.Administration.Logs; using Content.Server.Body.Systems; using Content.Server.DoAfter; +using Content.Server.Interaction; using Content.Server.Popups; using Content.Shared.CombatMode; +using Content.Shared.Chemistry; using Content.Shared.MobState.EntitySystems; namespace Content.Server.Chemistry.EntitySystems; @@ -10,9 +12,13 @@ namespace Content.Server.Chemistry.EntitySystems; public sealed partial class ChemistrySystem : EntitySystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly IEntityManager _entMan = default!; + [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly BloodstreamSystem _blood = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly ReactiveSystem _reactiveSystem = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedMobStateSystem _mobState = default!; [Dependency] private readonly SharedCombatModeSystem _combat = default!; [Dependency] private readonly SolutionContainerSystem _solutions = default!; diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs index 67ced4ede8..c4ba91d79a 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs @@ -1,9 +1,17 @@ using System.Linq; +using System.Diagnostics.CodeAnalysis; using Content.Server.Chemistry.Components; +using Content.Server.Chemistry.Components.SolutionManager; +using Content.Server.Weapons.Melee; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Database; +using Content.Shared.FixedPoint; +using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.Weapons.Melee; +using Content.Shared.MobState.Components; using Content.Shared.Weapons.Melee.Events; +using Robust.Shared.Player; namespace Content.Server.Chemistry.EntitySystems { @@ -21,7 +29,7 @@ namespace Content.Server.Chemistry.EntitySystems { if (args.Handled) return; - component.TryDoInject(args.User, args.User); + TryDoInject(uid, args.User, args.User); args.Handled = true; } @@ -30,7 +38,7 @@ namespace Content.Server.Chemistry.EntitySystems Dirty(component); } - public void OnAfterInteract(EntityUid uid, HyposprayComponent comp, AfterInteractEvent args) + public void OnAfterInteract(EntityUid uid, HyposprayComponent component, AfterInteractEvent args) { if (!args.CanReach) return; @@ -38,15 +46,92 @@ namespace Content.Server.Chemistry.EntitySystems var target = args.Target; var user = args.User; - comp.TryDoInject(target, user); + TryDoInject(uid, target, user); } - public void OnAttack(EntityUid uid, HyposprayComponent comp, MeleeHitEvent args) + public void OnAttack(EntityUid uid, HyposprayComponent component, MeleeHitEvent args) { if (!args.HitEntities.Any()) return; - comp.TryDoInject(args.HitEntities.First(), args.User); + TryDoInject(uid, args.HitEntities.First(), args.User); + } + + public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, HyposprayComponent? component=null) + { + if (!Resolve(uid, ref component)) + return false; + + if (!EligibleEntity(target, _entMan)) + return false; + + string? msgFormat = null; + + if (target == user) + msgFormat = "hypospray-component-inject-self-message"; + else if (EligibleEntity(user, _entMan) && _interaction.TryRollClumsy(user, component.ClumsyFailChance)) + { + msgFormat = "hypospray-component-inject-self-clumsy-message"; + target = user; + } + + _solutions.TryGetSolution(uid, component.SolutionName, out var hypoSpraySolution); + + if (hypoSpraySolution == null || hypoSpraySolution.CurrentVolume == 0) + { + _popup.PopupCursor(Loc.GetString("hypospray-component-empty-message"), Filter.Entities(user)); + return true; + } + + if (!_solutions.TryGetInjectableSolution(target.Value, out var targetSolution)) + { + _popup.PopupCursor(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan))), Filter.Entities(user)); + return false; + } + + _popup.PopupCursor(Loc.GetString(msgFormat ?? "hypospray-component-inject-other-message", ("other", target)), Filter.Entities(user)); + + if (target != user) + { + _popup.PopupCursor(Loc.GetString("hypospray-component-feel-prick-message"), Filter.Entities(target.Value)); + var meleeSys = EntitySystem.Get(); + var angle = Angle.FromWorldVec(_entMan.GetComponent(target.Value).WorldPosition - _entMan.GetComponent(user).WorldPosition); + // TODO: This should just be using melee attacks... + // meleeSys.SendLunge(angle, user); + } + + _audio.PlayPvs(component.InjectSound, user); + + // Get transfer amount. May be smaller than component.TransferAmount if not enough room + var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume); + + if (realTransferAmount <= 0) + { + _popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message",("owner", target)), Filter.Entities(user)); + return true; + } + + // Move units from attackSolution to targetSolution + var removedSolution = _solutions.SplitSolution(uid, hypoSpraySolution, realTransferAmount); + + if (!targetSolution.CanAddSolution(removedSolution)) + return true; + _reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection); + _solutions.TryAddSolution(target.Value, targetSolution, removedSolution); + + //same logtype as syringes... + _adminLogger.Add(LogType.ForceFeed, $"{_entMan.ToPrettyString(user):user} injected {_entMan.ToPrettyString(target.Value):target} with a solution {SolutionContainerSystem.ToPrettyString(removedSolution):removedSolution} using a {_entMan.ToPrettyString(uid):using}"); + + return true; + } + + static bool EligibleEntity([NotNullWhen(true)] EntityUid? entity, IEntityManager entMan) + { + // TODO: Does checking for BodyComponent make sense as a "can be hypospray'd" tag? + // In SS13 the hypospray ONLY works on mobs, NOT beakers or anything else. + + return entMan.HasComponent(entity) + && entMan.HasComponent(entity); } } }