| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- using Content.Server.Administration.Logs;
- using Content.Server.Atmos.EntitySystems;
- using Content.Server.Atmos.Piping.Components;
- using Content.Server.Atmos.Piping.Unary.EntitySystems;
- using Content.Server.Body.Components;
- using Content.Server.Body.Systems;
- using Content.Server.Medical.Components;
- using Content.Server.NodeContainer.EntitySystems;
- using Content.Server.NodeContainer.NodeGroups;
- using Content.Server.NodeContainer.Nodes;
- using Content.Server.Temperature.Components;
- using Content.Shared.Chemistry.EntitySystems;
- using Content.Shared.Atmos;
- using Content.Shared.UserInterface;
- using Content.Shared.Chemistry;
- using Content.Shared.Chemistry.Components;
- using Content.Shared.Chemistry.Components.SolutionManager;
- using Content.Shared.Climbing.Systems;
- using Content.Shared.Containers.ItemSlots;
- using Content.Shared.Database;
- using Content.Shared.DoAfter;
- using Content.Shared.DragDrop;
- using Content.Shared.Emag.Systems;
- using Content.Shared.Examine;
- using Content.Shared.Interaction;
- using Content.Shared.Medical.Cryogenics;
- using Content.Shared.MedicalScanner;
- using Content.Shared.Power;
- using Content.Shared.Verbs;
- using Robust.Server.GameObjects;
- using Robust.Shared.Containers;
- using Robust.Shared.Timing;
- using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem;
- using Content.Shared.Actions; // Shitmed Change
- using Content.Shared.Bed.Sleep; // Shitmed Change
- namespace Content.Server.Medical;
- public sealed partial class CryoPodSystem : SharedCryoPodSystem
- {
- [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
- [Dependency] private readonly GasCanisterSystem _gasCanisterSystem = default!;
- [Dependency] private readonly ClimbSystem _climbSystem = default!;
- [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
- [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
- [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
- [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
- [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
- [Dependency] private readonly SharedToolSystem _toolSystem = default!;
- [Dependency] private readonly IGameTiming _gameTiming = default!;
- [Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
- [Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
- [Dependency] private readonly IAdminLogManager _adminLogger = default!;
- [Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
- [Dependency] private readonly SleepingSystem _sleepingSystem = default!;
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent<CryoPodComponent, ComponentInit>(OnComponentInit);
- SubscribeLocalEvent<CryoPodComponent, GetVerbsEvent<AlternativeVerb>>(AddAlternativeVerbs);
- SubscribeLocalEvent<CryoPodComponent, GotEmaggedEvent>(OnEmagged);
- SubscribeLocalEvent<CryoPodComponent, CryoPodDragFinished>(OnDragFinished);
- SubscribeLocalEvent<CryoPodComponent, CryoPodPryFinished>(OnCryoPodPryFinished);
- SubscribeLocalEvent<CryoPodComponent, AtmosDeviceUpdateEvent>(OnCryoPodUpdateAtmosphere);
- SubscribeLocalEvent<CryoPodComponent, DragDropTargetEvent>(HandleDragDropOn);
- SubscribeLocalEvent<CryoPodComponent, InteractUsingEvent>(OnInteractUsing);
- SubscribeLocalEvent<CryoPodComponent, ExaminedEvent>(OnExamined);
- SubscribeLocalEvent<CryoPodComponent, PowerChangedEvent>(OnPowerChanged);
- SubscribeLocalEvent<CryoPodComponent, GasAnalyzerScanEvent>(OnGasAnalyzed);
- SubscribeLocalEvent<CryoPodComponent, ActivatableUIOpenAttemptEvent>(OnActivateUIAttempt);
- SubscribeLocalEvent<CryoPodComponent, AfterActivatableUIOpenEvent>(OnActivateUI);
- SubscribeLocalEvent<CryoPodComponent, EntRemovedFromContainerMessage>(OnEjected);
- }
- public override void Update(float frameTime)
- {
- base.Update(frameTime);
- var curTime = _gameTiming.CurTime;
- var bloodStreamQuery = GetEntityQuery<BloodstreamComponent>();
- var metaDataQuery = GetEntityQuery<MetaDataComponent>();
- var itemSlotsQuery = GetEntityQuery<ItemSlotsComponent>();
- var fitsInDispenserQuery = GetEntityQuery<FitsInDispenserComponent>();
- var solutionContainerManagerQuery = GetEntityQuery<SolutionContainerManagerComponent>();
- var query = EntityQueryEnumerator<ActiveCryoPodComponent, CryoPodComponent>();
- while (query.MoveNext(out var uid, out _, out var cryoPod))
- {
- metaDataQuery.TryGetComponent(uid, out var metaDataComponent);
- if (curTime < cryoPod.NextInjectionTime + _metaDataSystem.GetPauseTime(uid, metaDataComponent))
- continue;
- cryoPod.NextInjectionTime = curTime + TimeSpan.FromSeconds(cryoPod.BeakerTransferTime);
- if (!itemSlotsQuery.TryGetComponent(uid, out var itemSlotsComponent))
- {
- continue;
- }
- var container = _itemSlotsSystem.GetItemOrNull(uid, cryoPod.SolutionContainerName, itemSlotsComponent);
- var patient = cryoPod.BodyContainer.ContainedEntity;
- if (container != null
- && container.Value.Valid
- && patient != null
- && fitsInDispenserQuery.TryGetComponent(container, out var fitsInDispenserComponent)
- && solutionContainerManagerQuery.TryGetComponent(container,
- out var solutionContainerManagerComponent)
- && _solutionContainerSystem.TryGetFitsInDispenser((container.Value, fitsInDispenserComponent, solutionContainerManagerComponent),
- out var containerSolution, out _))
- {
- if (!bloodStreamQuery.TryGetComponent(patient, out var bloodstream))
- {
- continue;
- }
- var solutionToInject = _solutionContainerSystem.SplitSolution(containerSolution.Value, cryoPod.BeakerTransferAmount);
- _bloodstreamSystem.TryAddToChemicals(patient.Value, solutionToInject, bloodstream);
- _reactiveSystem.DoEntityReaction(patient.Value, solutionToInject, ReactionMethod.Injection);
- }
- }
- }
- public override EntityUid? EjectBody(EntityUid uid, CryoPodComponent? cryoPodComponent)
- {
- if (!Resolve(uid, ref cryoPodComponent))
- return null;
- if (cryoPodComponent.BodyContainer.ContainedEntity is not { Valid: true } contained)
- return null;
- base.EjectBody(uid, cryoPodComponent);
- _climbSystem.ForciblySetClimbing(contained, uid);
- return contained;
- }
- #region Interaction
- private void HandleDragDropOn(Entity<CryoPodComponent> entity, ref DragDropTargetEvent args)
- {
- if (entity.Comp.BodyContainer.ContainedEntity != null)
- return;
- var doAfterArgs = new DoAfterArgs(EntityManager, args.User, entity.Comp.EntryDelay, new CryoPodDragFinished(), entity, target: args.Dragged, used: entity)
- {
- BreakOnDamage = true,
- BreakOnMove = true,
- NeedHand = false,
- };
- _doAfterSystem.TryStartDoAfter(doAfterArgs);
- args.Handled = true;
- }
- private void OnDragFinished(Entity<CryoPodComponent> entity, ref CryoPodDragFinished args)
- {
- if (args.Cancelled || args.Handled || args.Args.Target == null)
- return;
- if (InsertBody(entity.Owner, args.Args.Target.Value, entity.Comp))
- {
- if (!TryComp(entity.Owner, out CryoPodAirComponent? cryoPodAir))
- _adminLogger.Add(LogType.Action, LogImpact.Medium,
- $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(entity.Owner)}");
- _adminLogger.Add(LogType.Action, LogImpact.Medium,
- $"{ToPrettyString(args.User)} inserted {ToPrettyString(args.Args.Target.Value)} into {ToPrettyString(entity.Owner)} which contains gas: {cryoPodAir!.Air.ToPrettyString():gasMix}");
- }
- args.Handled = true;
- }
- private void OnActivateUIAttempt(Entity<CryoPodComponent> entity, ref ActivatableUIOpenAttemptEvent args)
- {
- if (args.Cancelled)
- {
- return;
- }
- var containedEntity = entity.Comp.BodyContainer.ContainedEntity;
- if (containedEntity == null || containedEntity == args.User || !HasComp<ActiveCryoPodComponent>(entity))
- {
- args.Cancel();
- }
- }
- private void OnActivateUI(Entity<CryoPodComponent> entity, ref AfterActivatableUIOpenEvent args)
- {
- if (!entity.Comp.BodyContainer.ContainedEntity.HasValue)
- return;
- TryComp<TemperatureComponent>(entity.Comp.BodyContainer.ContainedEntity, out var temp);
- TryComp<BloodstreamComponent>(entity.Comp.BodyContainer.ContainedEntity, out var bloodstream);
- if (TryComp<HealthAnalyzerComponent>(entity, out var healthAnalyzer))
- {
- healthAnalyzer.ScannedEntity = entity.Comp.BodyContainer.ContainedEntity;
- }
- // TODO: This should be a state my dude
- _uiSystem.ServerSendUiMessage(
- entity.Owner,
- HealthAnalyzerUiKey.Key,
- new HealthAnalyzerScannedUserMessage(GetNetEntity(entity.Comp.BodyContainer.ContainedEntity),
- temp?.CurrentTemperature ?? 0,
- (bloodstream != null && _solutionContainerSystem.ResolveSolution(entity.Comp.BodyContainer.ContainedEntity.Value,
- bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
- ? bloodSolution.FillFraction
- : 0,
- null,
- null,
- null,
- null // Shitmed Change
- ));
- }
- private void OnInteractUsing(Entity<CryoPodComponent> entity, ref InteractUsingEvent args)
- {
- if (args.Handled || !entity.Comp.Locked || entity.Comp.BodyContainer.ContainedEntity == null)
- return;
- args.Handled = _toolSystem.UseTool(args.Used, args.User, entity.Owner, entity.Comp.PryDelay, "Prying", new CryoPodPryFinished());
- }
- private void OnExamined(Entity<CryoPodComponent> entity, ref ExaminedEvent args)
- {
- var container = _itemSlotsSystem.GetItemOrNull(entity.Owner, entity.Comp.SolutionContainerName);
- if (args.IsInDetailsRange && container != null && _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out _, out var containerSolution))
- {
- using (args.PushGroup(nameof(CryoPodComponent)))
- {
- args.PushMarkup(Loc.GetString("cryo-pod-examine", ("beaker", Name(container.Value))));
- if (containerSolution.Volume == 0)
- {
- args.PushMarkup(Loc.GetString("cryo-pod-empty-beaker"));
- }
- }
- }
- }
- private void OnPowerChanged(Entity<CryoPodComponent> entity, ref PowerChangedEvent args)
- {
- // Needed to avoid adding/removing components on a deleted entity
- if (Terminating(entity))
- {
- return;
- }
- var insidePod = entity.Comp.BodyContainer.ContainedEntity; // Shitmed Change
- if (args.Powered)
- {
- EnsureComp<ActiveCryoPodComponent>(entity);
- }
- else
- {
- RemComp<ActiveCryoPodComponent>(entity);
- if (insidePod is { } patient) // Shitmed Change
- _sleepingSystem.TryWaking(patient);
- _uiSystem.CloseUi(entity.Owner, HealthAnalyzerUiKey.Key);
- }
- UpdateAppearance(entity.Owner, entity.Comp);
- }
- #endregion
- #region Atmos handler
- private void OnCryoPodUpdateAtmosphere(Entity<CryoPodComponent> entity, ref AtmosDeviceUpdateEvent args)
- {
- if (!_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PortablePipeNode? portNode))
- return;
- if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir))
- return;
- _atmosphereSystem.React(cryoPodAir.Air, portNode);
- if (portNode.NodeGroup is PipeNet { NodeCount: > 1 } net)
- {
- _gasCanisterSystem.MixContainerWithPipeNet(cryoPodAir.Air, net.Air);
- }
- }
- private void OnGasAnalyzed(Entity<CryoPodComponent> entity, ref GasAnalyzerScanEvent args)
- {
- if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir))
- return;
- args.GasMixtures ??= new List<(string, GasMixture?)>();
- args.GasMixtures.Add((Name(entity.Owner), cryoPodAir.Air));
- // If it's connected to a port, include the port side
- // multiply by volume fraction to make sure to send only the gas inside the analyzed pipe element, not the whole pipe system
- if (_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PipeNode? port) && port.Air.Volume != 0f)
- {
- var portAirLocal = port.Air.Clone();
- portAirLocal.Multiply(port.Volume / port.Air.Volume);
- portAirLocal.Volume = port.Volume;
- args.GasMixtures.Add((entity.Comp.PortName, portAirLocal));
- }
- }
- private void OnEjected(Entity<CryoPodComponent> cryoPod, ref EntRemovedFromContainerMessage args)
- {
- if (TryComp<HealthAnalyzerComponent>(cryoPod.Owner, out var healthAnalyzer))
- {
- healthAnalyzer.ScannedEntity = null;
- }
- // if body is ejected - no need to display health-analyzer
- _uiSystem.CloseUi(cryoPod.Owner, HealthAnalyzerUiKey.Key);
- }
- #endregion
- }
|