using Content.Shared.Alert; using Content.Shared.DoAfter; using Content.Shared.Ensnaring; using Content.Shared.Ensnaring.Components; using Content.Shared.IdentityManagement; using Content.Shared.StepTrigger.Systems; using Content.Shared.Throwing; namespace Content.Server.Ensnaring; public sealed partial class EnsnareableSystem { [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly AlertsSystem _alerts = default!; public void InitializeEnsnaring() { SubscribeLocalEvent(OnComponentRemove); SubscribeLocalEvent(AttemptStepTrigger); SubscribeLocalEvent(OnStepTrigger); SubscribeLocalEvent(OnThrowHit); } private void OnComponentRemove(EntityUid uid, EnsnaringComponent component, ComponentRemove args) { if (!TryComp(component.Ensnared, out var ensnared)) return; if (ensnared.IsEnsnared) ForceFree(uid, component); } private void AttemptStepTrigger(EntityUid uid, EnsnaringComponent component, ref StepTriggerAttemptEvent args) { args.Continue = true; } private void OnStepTrigger(EntityUid uid, EnsnaringComponent component, ref StepTriggeredEvent args) { TryEnsnare(args.Tripper, uid, component); } private void OnThrowHit(EntityUid uid, EnsnaringComponent component, ThrowDoHitEvent args) { if (!component.CanThrowTrigger) return; TryEnsnare(args.Target, uid, component); } /// /// Used where you want to try to ensnare an entity with the /// /// The entity that will be ensnared /// The entity that is used to ensnare /// The ensnaring component public void TryEnsnare(EntityUid target, EntityUid ensnare, EnsnaringComponent component) { //Don't do anything if they don't have the ensnareable component. if (!TryComp(target, out var ensnareable)) return; component.Ensnared = target; ensnareable.Container.Insert(ensnare); ensnareable.IsEnsnared = true; Dirty(ensnareable); UpdateAlert(ensnare, ensnareable); var ev = new EnsnareEvent(component.WalkSpeed, component.SprintSpeed); RaiseLocalEvent(target, ev); } /// /// Used where you want to try to free an entity with the /// /// The entity that will be freed /// The entity that is freeing the target /// The entity used to ensnare /// The ensnaring component public void TryFree(EntityUid target, EntityUid user, EntityUid ensnare, EnsnaringComponent component) { //Don't do anything if they don't have the ensnareable component. if (!HasComp(target)) return; var freeTime = user == target ? component.BreakoutTime : component.FreeTime; var breakOnMove = user != target || !component.CanMoveBreakout; var doAfterEventArgs = new DoAfterArgs(user, freeTime, new EnsnareableDoAfterEvent(), target, target: target, used: ensnare) { BreakOnUserMove = breakOnMove, BreakOnTargetMove = breakOnMove, BreakOnDamage = false, NeedHand = true, BlockDuplicate = true, }; if (!_doAfter.TryStartDoAfter(doAfterEventArgs)) return; if (user == target) _popup.PopupEntity(Loc.GetString("ensnare-component-try-free", ("ensnare", ensnare)), target, target); else _popup.PopupEntity(Loc.GetString("ensnare-component-try-free-other", ("ensnare", ensnare), ("user", Identity.Entity(target, EntityManager))), user, user); } /// /// Used to force free someone for things like if the is removed /// public void ForceFree(EntityUid ensnare, EnsnaringComponent component) { if (!TryComp(component.Ensnared, out var ensnareable)) return; ensnareable.Container.ForceRemove(ensnare); ensnareable.IsEnsnared = false; Dirty(ensnareable); component.Ensnared = null; UpdateAlert(ensnare, ensnareable); var ev = new EnsnareRemoveEvent(); RaiseLocalEvent(ensnare, ev); } public void UpdateAlert(EntityUid ensnare, EnsnareableComponent component) { if (!component.IsEnsnared) _alerts.ClearAlert(ensnare, AlertType.Ensnared); else _alerts.ShowAlert(ensnare, AlertType.Ensnared); } }