]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
emag medibot to make it poison patients (#15377)
authordeltanedas <39013340+deltanedas@users.noreply.github.com>
Tue, 2 May 2023 08:00:57 +0000 (08:00 +0000)
committerGitHub <noreply@github.com>
Tue, 2 May 2023 08:00:57 +0000 (18:00 +1000)
Co-authored-by: deltanedas <@deltanedas:kde.org>
Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/MedibotInjectOperator.cs
Content.Server/Silicons/Bots/MedibotComponent.cs [deleted file]
Content.Shared/Silicons/Bots/EmaggableMedibotComponent.cs [new file with mode: 0644]
Content.Shared/Silicons/Bots/MedibotComponent.cs [new file with mode: 0644]
Content.Shared/Silicons/Bots/MedibotSystem.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml

index eadeb67d48ea93bc8de1cf2f47fcce578d028b82..0b65ac055cea7511c2a635200ad958d86a743976 100644 (file)
@@ -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!;
 
     /// <summary>
     /// 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<SharedAudioSystem>();
         _chat = sysManager.GetEntitySystem<ChatSystem>();
-        _interactionSystem = sysManager.GetEntitySystem<SharedInteractionSystem>();
-        _popupSystem = sysManager.GetEntitySystem<SharedPopupSystem>();
-        _solutionSystem = sysManager.GetEntitySystem<SolutionContainerSystem>();
+        _interaction = sysManager.GetEntitySystem<SharedInteractionSystem>();
+        _popup = sysManager.GetEntitySystem<SharedPopupSystem>();
+        _solution = sysManager.GetEntitySystem<SolutionContainerSystem>();
     }
 
     public override void Shutdown(NPCBlackboard blackboard, HTNOperatorStatus status)
@@ -44,41 +47,48 @@ public sealed class MedibotInjectOperator : HTNOperator
         // TODO: Wat
         var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
 
-        if (!blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entManager) || _entManager.Deleted(target))
+        if (!blackboard.TryGetValue<EntityUid>(TargetKey, out var target, _entMan) || _entMan.Deleted(target))
             return HTNOperatorStatus.Failed;
 
-        if (!_entManager.TryGetComponent<MedibotComponent>(owner, out var botComp))
+        if (!_entMan.TryGetComponent<MedibotComponent>(owner, out var botComp))
             return HTNOperatorStatus.Failed;
 
         // To avoid spam, the rest of this needs fixing.
-        _entManager.EnsureComponent<NPCRecentlyInjectedComponent>(target);
+        _entMan.EnsureComponent<NPCRecentlyInjectedComponent>(target);
 
-        if (!_entManager.TryGetComponent<DamageableComponent>(target, out var damage))
+        if (!_entMan.TryGetComponent<DamageableComponent>(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<EmaggedComponent>(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 (file)
index 8d6083a..0000000
+++ /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
-    {
-        /// <summary>
-        /// Med the bot will inject when UNDER the standard med damage threshold.
-        /// </summary>
-        [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
-        public string StandardMed = "Tricordrazine";
-
-        [DataField("standardMedInjectAmount")]
-        public float StandardMedInjectAmount = 15f;
-        public const float StandardMedDamageThreshold = 50f;
-
-        /// <summary>
-        /// Med the bot will inject when OVER the emergency med damage threshold.
-        /// </summary>
-        [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
-        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 (file)
index 0000000..47fb940
--- /dev/null
@@ -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;
+
+/// <summary>
+/// Replaced the medibot's meds with these when emagged. Could be poison, could be fun.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(MedibotSystem))]
+public sealed partial class EmaggableMedibotComponent : Component
+{
+    /// <summary>
+    /// Med the bot will inject when UNDER the standard med damage threshold.
+    /// </summary>
+    [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public string StandardMed = "Tricordrazine";
+
+    [DataField("standardMedAmount"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public float StandardMedAmount = 15f;
+
+    /// <summary>
+    /// Med the bot will inject when OVER the emergency med damage threshold.
+    /// </summary>
+    [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public string EmergencyMed = "Inaprovaline";
+
+    [DataField("emergencyMedAmount"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+    public float EmergencyMedAmount = 15f;
+
+    /// <summary>
+    /// Sound to play when the bot has been emagged
+    /// </summary>
+    [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 (file)
index 0000000..b0b6139
--- /dev/null
@@ -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;
+
+/// <summary>
+/// Used by the server for NPC medibot injection.
+/// Currently no clientside prediction done, only exists in shared for emag handling.
+/// </summary>
+[RegisterComponent]
+[Access(typeof(MedibotSystem))]
+public sealed class MedibotComponent : Component
+{
+    /// <summary>
+    /// Med the bot will inject when UNDER the standard med damage threshold.
+    /// </summary>
+    [DataField("standardMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
+    public string StandardMed = "Tricordrazine";
+
+    [DataField("standardMedAmount")]
+    public float StandardMedAmount = 15f;
+
+    /// <summary>
+    /// Med the bot will inject when OVER the emergency med damage threshold.
+    /// </summary>
+    [DataField("emergencyMed", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
+    public string EmergencyMed = "Inaprovaline";
+
+    [DataField("emergencyMedAmount")]
+    public float EmergencyMedAmount = 15f;
+
+    /// <summary>
+    /// Sound played after injecting a patient.
+    /// </summary>
+    [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 (file)
index 0000000..fe88cba
--- /dev/null
@@ -0,0 +1,33 @@
+using Content.Shared.Emag.Systems;
+using Robust.Shared.Audio;
+
+namespace Content.Shared.Silicons.Bots;
+
+/// <summary>
+/// Handles emagging medibots
+/// </summary>
+public sealed class MedibotSystem : EntitySystem
+{
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<EmaggableMedibotComponent, GotEmaggedEvent>(OnEmagged);
+    }
+
+    private void OnEmagged(EntityUid uid, EmaggableMedibotComponent comp, ref GotEmaggedEvent args)
+    {
+        if (!TryComp<MedibotComponent>(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;
+    }
+}
index 1faa7ec9a08c5936913c9987b8a18752a7e4ff6c..43826865162ac2099dcdb4c2237a98baf2dd5605 100644 (file)
   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