From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Tue, 2 May 2023 08:00:57 +0000 (+0000) Subject: emag medibot to make it poison patients (#15377) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=aceb354945ae207bab9b4696aac6b472a7c257dc;p=space-station-14.git emag medibot to make it poison patients (#15377) Co-authored-by: deltanedas <@deltanedas:kde.org> --- diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs index eadeb67d48..0b65ac055c 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs @@ -1,10 +1,11 @@ using Content.Server.Chat.Systems; using Content.Server.Chemistry.EntitySystems; using Content.Server.NPC.Components; -using Content.Server.Silicons.Bots; using Content.Shared.Damage; +using Content.Shared.Emag.Components; using Content.Shared.Interaction; using Content.Shared.Popups; +using Content.Shared.Silicons.Bots; using Robust.Shared.Audio; using Robust.Shared.Player; @@ -12,11 +13,12 @@ namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Specific; public sealed class MedibotInjectOperator : HTNOperator { - [Dependency] private readonly IEntityManager _entManager = default!; + [Dependency] private readonly IEntityManager _entMan = default!; + private SharedAudioSystem _audio = default!; private ChatSystem _chat = default!; - private SharedInteractionSystem _interactionSystem = default!; - private SharedPopupSystem _popupSystem = default!; - private SolutionContainerSystem _solutionSystem = default!; + private SharedInteractionSystem _interaction = default!; + private SharedPopupSystem _popup = default!; + private SolutionContainerSystem _solution = default!; /// /// Target entity to inject. @@ -27,10 +29,11 @@ public sealed class MedibotInjectOperator : HTNOperator public override void Initialize(IEntitySystemManager sysManager) { base.Initialize(sysManager); + _audio = sysManager.GetEntitySystem(); _chat = sysManager.GetEntitySystem(); - _interactionSystem = sysManager.GetEntitySystem(); - _popupSystem = sysManager.GetEntitySystem(); - _solutionSystem = sysManager.GetEntitySystem(); + _interaction = sysManager.GetEntitySystem(); + _popup = sysManager.GetEntitySystem(); + _solution = sysManager.GetEntitySystem(); } public override void Shutdown(NPCBlackboard blackboard, HTNOperatorStatus status) @@ -44,41 +47,48 @@ public sealed class MedibotInjectOperator : HTNOperator // TODO: Wat var owner = blackboard.GetValue(NPCBlackboard.Owner); - if (!blackboard.TryGetValue(TargetKey, out var target, _entManager) || _entManager.Deleted(target)) + if (!blackboard.TryGetValue(TargetKey, out var target, _entMan) || _entMan.Deleted(target)) return HTNOperatorStatus.Failed; - if (!_entManager.TryGetComponent(owner, out var botComp)) + if (!_entMan.TryGetComponent(owner, out var botComp)) return HTNOperatorStatus.Failed; // To avoid spam, the rest of this needs fixing. - _entManager.EnsureComponent(target); + _entMan.EnsureComponent(target); - if (!_entManager.TryGetComponent(target, out var damage)) + if (!_entMan.TryGetComponent(target, out var damage)) return HTNOperatorStatus.Failed; - if (!_solutionSystem.TryGetInjectableSolution(target, out var injectable)) + if (!_solution.TryGetInjectableSolution(target, out var injectable)) return HTNOperatorStatus.Failed; - if (!_interactionSystem.InRangeUnobstructed(owner, target)) + if (!_interaction.InRangeUnobstructed(owner, target)) return HTNOperatorStatus.Failed; - if (damage.TotalDamage == 0) + // if emagged, always treat below-crit as injured (give funny juice to healthy people) + var total = damage.TotalDamage; + if (_entMan.HasComponent(owner) && total < MedibotComponent.EmergencyMedDamageThreshold) + { + total = MedibotComponent.EmergencyMedDamageThreshold; + } + + if (total == 0) return HTNOperatorStatus.Failed; - if (damage.TotalDamage >= MedibotComponent.EmergencyMedDamageThreshold) + if (total >= MedibotComponent.EmergencyMedDamageThreshold) { - _solutionSystem.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedInjectAmount, out var accepted); - _popupSystem.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target); - SoundSystem.Play("/Audio/Items/hypospray.ogg", Filter.Pvs(target), target); + _solution.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedAmount, out var accepted); + _popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target); + _audio.PlayPvs(botComp.InjectSound, target); _chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, hideChat: false, hideGlobalGhostChat: true); return HTNOperatorStatus.Finished; } - if (damage.TotalDamage >= MedibotComponent.StandardMedDamageThreshold) + if (total >= MedibotComponent.StandardMedDamageThreshold) { - _solutionSystem.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedInjectAmount, out var accepted); - _popupSystem.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target); - SoundSystem.Play("/Audio/Items/hypospray.ogg", Filter.Pvs(target), target); + _solution.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedAmount, out var accepted); + _popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target); + _audio.PlayPvs(botComp.InjectSound, target); _chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, hideChat: false, hideGlobalGhostChat: true); return HTNOperatorStatus.Finished; } diff --git a/Content.Server/Silicons/Bots/MedibotComponent.cs b/Content.Server/Silicons/Bots/MedibotComponent.cs deleted file mode 100644 index 8d6083a24e..0000000000 --- a/Content.Server/Silicons/Bots/MedibotComponent.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Content.Shared.Chemistry.Reagent; - -namespace Content.Server.Silicons.Bots -{ - [RegisterComponent] - public sealed class MedibotComponent : Component - { - /// - /// Med the bot will inject when UNDER the standard med damage threshold. - /// - [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string StandardMed = "Tricordrazine"; - - [DataField("standardMedInjectAmount")] - public float StandardMedInjectAmount = 15f; - public const float StandardMedDamageThreshold = 50f; - - /// - /// Med the bot will inject when OVER the emergency med damage threshold. - /// - [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string EmergencyMed = "Inaprovaline"; - - [DataField("emergencyMedInjectAmount")] - public float EmergencyMedInjectAmount = 15f; - - public const float EmergencyMedDamageThreshold = 100f; - - } -} diff --git a/Content.Shared/Silicons/Bots/EmaggableMedibotComponent.cs b/Content.Shared/Silicons/Bots/EmaggableMedibotComponent.cs new file mode 100644 index 0000000000..47fb940786 --- /dev/null +++ b/Content.Shared/Silicons/Bots/EmaggableMedibotComponent.cs @@ -0,0 +1,38 @@ +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Silicons.Bots; + +/// +/// Replaced the medibot's meds with these when emagged. Could be poison, could be fun. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(MedibotSystem))] +public sealed partial class EmaggableMedibotComponent : Component +{ + /// + /// Med the bot will inject when UNDER the standard med damage threshold. + /// + [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public string StandardMed = "Tricordrazine"; + + [DataField("standardMedAmount"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float StandardMedAmount = 15f; + + /// + /// Med the bot will inject when OVER the emergency med damage threshold. + /// + [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public string EmergencyMed = "Inaprovaline"; + + [DataField("emergencyMedAmount"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float EmergencyMedAmount = 15f; + + /// + /// Sound to play when the bot has been emagged + /// + [DataField("sparkSound")] + public SoundSpecifier SparkSound = new SoundCollectionSpecifier("sparks"); +} diff --git a/Content.Shared/Silicons/Bots/MedibotComponent.cs b/Content.Shared/Silicons/Bots/MedibotComponent.cs new file mode 100644 index 0000000000..b0b61390bb --- /dev/null +++ b/Content.Shared/Silicons/Bots/MedibotComponent.cs @@ -0,0 +1,41 @@ +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Audio; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Silicons.Bots; + +/// +/// Used by the server for NPC medibot injection. +/// Currently no clientside prediction done, only exists in shared for emag handling. +/// +[RegisterComponent] +[Access(typeof(MedibotSystem))] +public sealed class MedibotComponent : Component +{ + /// + /// Med the bot will inject when UNDER the standard med damage threshold. + /// + [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string StandardMed = "Tricordrazine"; + + [DataField("standardMedAmount")] + public float StandardMedAmount = 15f; + + /// + /// Med the bot will inject when OVER the emergency med damage threshold. + /// + [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string EmergencyMed = "Inaprovaline"; + + [DataField("emergencyMedAmount")] + public float EmergencyMedAmount = 15f; + + /// + /// Sound played after injecting a patient. + /// + [DataField("injectSound")] + public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg"); + + public const float StandardMedDamageThreshold = 50f; + public const float EmergencyMedDamageThreshold = 100f; +} diff --git a/Content.Shared/Silicons/Bots/MedibotSystem.cs b/Content.Shared/Silicons/Bots/MedibotSystem.cs new file mode 100644 index 0000000000..fe88cbae5c --- /dev/null +++ b/Content.Shared/Silicons/Bots/MedibotSystem.cs @@ -0,0 +1,33 @@ +using Content.Shared.Emag.Systems; +using Robust.Shared.Audio; + +namespace Content.Shared.Silicons.Bots; + +/// +/// Handles emagging medibots +/// +public sealed class MedibotSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnEmagged); + } + + private void OnEmagged(EntityUid uid, EmaggableMedibotComponent comp, ref GotEmaggedEvent args) + { + if (!TryComp(uid, out var medibot)) + return; + + _audio.PlayPredicted(comp.SparkSound, uid, args.UserUid, AudioParams.Default.WithVolume(8)); + + medibot.StandardMed = comp.StandardMed; + medibot.StandardMedAmount = comp.StandardMedAmount; + medibot.EmergencyMed = comp.EmergencyMed; + medibot.EmergencyMedAmount = comp.EmergencyMedAmount; + args.Handled = true; + } +} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 1faa7ec9a0..4382686516 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -239,6 +239,13 @@ description: No substitute for a doctor, but better than nothing. components: - type: Medibot + - type: EmaggableMedibot + # when you are fine, medibot will help you go sleep + standardMed: ChloralHydrate + standardMedAmount: 5 + # when you are crit, medibot will help you have fun + emergencyMed: SpaceDrugs + emergencyMedAmount: 25 - type: Sprite drawdepth: Mobs sprite: Mobs/Silicon/Bots/medibot.rsi