using System.Linq; using Content.Shared.Actions; using Content.Shared.Atmos.Rotting; using Content.Shared.Changeling.Components; using Content.Shared.Cuffs; using Content.Shared.Ensnaring; using Content.Shared.Fluids; using Content.Shared.IdentityManagement; using Content.Shared.Movement.Pulling.Systems; using Content.Shared.Popups; using Content.Shared.Stunnable; using Robust.Shared.Audio.Systems; namespace Content.Shared.Changeling.Systems; public sealed partial class ChangelingAbilitySystem : EntitySystem { [Dependency] private SharedAudioSystem _audio = default!; [Dependency] private SharedPopupSystem _popup = default!; [Dependency] private SharedCuffableSystem _cuffable = default!; [Dependency] private SharedEnsnareableSystem _snare = default!; [Dependency] private PullingSystem _pulling = default!; [Dependency] private SharedStunSystem _stun = default!; [Dependency] private SharedPuddleSystem _puddle = default!; [Dependency] private SharedChangelingIdentitySystem _changelingIdentity = default!; [Dependency] private ChangelingDevourSystem _changelingDevour = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnBiodegradeAction); SubscribeLocalEvent(OnStingDna); } private void OnBiodegradeAction(Entity ent, ref ChangelingBiodegradeActionEvent args) { // Nothing can be done :( if (!_cuffable.IsCuffed(args.Performer) && !_snare.IsEnsnared(args.Performer)) return; if (_pulling.GetPuller(args.Performer) is { } puller) { _stun.TryAddParalyzeDuration(puller, ent.Comp.PullerStunDuration); } var toDelete = new List(); _cuffable.TryGetAllCuffs(args.Performer, out var cuffs); foreach (var cuff in cuffs.ToList()) { _cuffable.Uncuff(args.Performer, args.Performer, cuff); toDelete.Add(cuff); } toDelete.AddRange(_snare.ForceFreeAll(args.Performer)); args.Handled = true; var selfPopup = Loc.TryGetString(ent.Comp.ActivatedPopupSelf, out var self, ("user", Identity.Entity(args.Performer, EntityManager)), ("restraint", toDelete.First())) ? self : null; var othersPopup = Loc.TryGetString(ent.Comp.ActivatedPopup, out var others, ("user", Identity.Entity(args.Performer, EntityManager)), ("restraint", toDelete.First())) ? others : null; _popup.PopupEntity(selfPopup, othersPopup, args.Performer, args.Performer, PopupType.LargeCaution); _audio.PlayPredicted(ent.Comp.ActivatedSound, args.Performer, args.Performer); foreach (var deleted in toDelete) { PredictedQueueDel(deleted); } if (ent.Comp.SpillSolution != null) _puddle.TrySpillAt(args.Performer, ent.Comp.SpillSolution, out _, false); } private void OnStingDna(Entity ent, ref ChangelingStingDnaEvent args) { if (args.Target == ent.Owner) return; // Can't sting yourself. if (!_changelingDevour.CanDevour(ent.Owner, args.Target, checkDead: false, checkProtected: false)) return; _changelingIdentity.GrantIdentity(ent.AsNullable(), args.Target); args.Handled = true; } } /// /// Action event for the Dna sting ability. Used to grand the changeling an identity without devouring somebody. /// public sealed partial class ChangelingStingDnaEvent : EntityTargetActionEvent;