using Content.Shared.Actions; using Content.Shared.Implants.Components; using Robust.Shared.Containers; using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Shared.Implants; public abstract partial class SharedSubdermalImplantSystem : EntitySystem { [Dependency] private readonly SharedActionsSystem _actions = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly IGameTiming _timing = default!; public override void Initialize() { base.Initialize(); InitializeRelay(); SubscribeLocalEvent(OnInsert); SubscribeLocalEvent(OnRemoveAttempt); SubscribeLocalEvent(OnRemove); } private void OnInsert(Entity ent, ref EntGotInsertedIntoContainerMessage args) { // The results of the container change are already networked on their own if (_timing.ApplyingState) return; if (args.Container.ID != ImplanterComponent.ImplantSlotId) return; ent.Comp.ImplantedEntity = args.Container.Owner; Dirty(ent); EntityManager.AddComponents(ent.Comp.ImplantedEntity.Value, ent.Comp.ImplantComponents); if (ent.Comp.ImplantAction != null) _actions.AddAction(ent.Comp.ImplantedEntity.Value, ref ent.Comp.Action, ent.Comp.ImplantAction, ent.Owner); var ev = new ImplantImplantedEvent(ent.Owner, ent.Comp.ImplantedEntity.Value); RaiseLocalEvent(ent.Owner, ref ev); } private void OnRemoveAttempt(Entity ent, ref ContainerGettingRemovedAttemptEvent args) { if (ent.Comp.Permanent && ent.Comp.ImplantedEntity != null) args.Cancel(); } private void OnRemove(Entity ent, ref EntGotRemovedFromContainerMessage args) { // The results of the container change are already networked on their own if (_timing.ApplyingState) return; if (args.Container.ID != ImplanterComponent.ImplantSlotId) return; if (ent.Comp.ImplantedEntity == null || Terminating(ent.Comp.ImplantedEntity.Value)) return; EntityManager.RemoveComponents(ent.Comp.ImplantedEntity.Value, ent.Comp.ImplantComponents); _actions.RemoveAction(ent.Comp.ImplantedEntity.Value, ent.Comp.Action); ent.Comp.Action = null; var ev = new ImplantRemovedEvent(ent.Owner, ent.Comp.ImplantedEntity.Value); RaiseLocalEvent(ent.Owner, ref ev); ent.Comp.ImplantedEntity = null; Dirty(ent); } /// /// Add a list of implants to a person. /// Logs any implant ids that don't have . /// public void AddImplants(EntityUid uid, IEnumerable implants) { foreach (var id in implants) { AddImplant(uid, id); } } /// /// Adds a single implant to a person, and returns the implant. /// Logs any implant ids that don't have . /// /// /// The implant, if it was successfully created. Otherwise, null. /// > public EntityUid? AddImplant(EntityUid target, EntProtoId implantId) { if (_net.IsClient) return null; // can't interact with predicted spawns yet var coords = Transform(target).Coordinates; var implant = Spawn(implantId, coords); if (TryComp(implant, out var implantComp)) { ForceImplant(target, (implant, implantComp)); } else { Log.Warning($"Tried to inject implant '{implantId}' without SubdermalImplantComponent into {ToPrettyString(target):implanted}"); Del(implant); return null; } return implant; } /// /// Forces an implant into a person /// Good for on spawn related code or admin additions /// /// The entity to be implanted /// The implant public void ForceImplant(EntityUid target, Entity implant) { if (!Resolve(implant, ref implant.Comp)) return; //If the target doesn't have the implanted component, add it. var implantedComp = EnsureComp(target); implant.Comp.ImplantedEntity = target; _container.Insert(implant.Owner, implantedComp.ImplantContainer); } /// /// Force remove a singular implant /// /// the implanted entity /// the implant public void ForceRemove(Entity target, EntityUid implant) { if (!Resolve(target, ref target.Comp)) return; _container.Remove(implant, target.Comp.ImplantContainer); PredictedQueueDel(implant); } /// /// Removes and deletes implants by force /// /// The entity to have implants removed public void WipeImplants(Entity target) { if (!Resolve(target, ref target.Comp, false)) return; _container.CleanContainer(target.Comp.ImplantContainer); } } /// /// Event that is raised whenever someone is implanted with any given implant. /// Raised on the the implant entity. /// /// /// implant implant implant implant /// [ByRefEvent] public readonly record struct ImplantImplantedEvent { public readonly EntityUid Implant; public readonly EntityUid Implanted; public ImplantImplantedEvent(EntityUid implant, EntityUid implanted) { Implant = implant; Implanted = implanted; } } /// /// Event that is raised whenever an implant is removed from someone. /// Raised on the the implant entity. /// [ByRefEvent] public readonly record struct ImplantRemovedEvent { public readonly EntityUid Implant; public readonly EntityUid Implanted; public ImplantRemovedEvent(EntityUid implant, EntityUid implanted) { Implant = implant; Implanted = implanted; } }