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;
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.
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)
// 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;
}
--- /dev/null
+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");
+}
--- /dev/null
+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;
+}