using System.Linq; using System.Threading.Tasks; using Content.Server.Explosion.EntitySystems; using Content.Server.Popups; using Content.Shared.Clothing; using Content.Shared.Clothing.Components; using Content.Shared.Clothing.EntitySystems; using Content.Shared.Damage; using Content.Shared.Damage.Systems; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Mobs; using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Tag; using Content.Shared.Trigger.Systems; using Robust.Server.Audio; namespace Content.Server._Sunrise.ExpCollars; /// /// Система для взрывного ошейника. /// public sealed class ExpCollarsSystem : EntitySystem { [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly TriggerSystem _trigger = default!; [Dependency] private readonly ClothingSystem _clothing = default!; [Dependency] private readonly TagSystem _tag = default!; /// public override void Initialize() { SubscribeLocalEvent(OnInteraction); SubscribeLocalEvent(OnMobStateChanged); SubscribeLocalEvent(OnEquipped); SubscribeLocalEvent(OnUnequipped); SubscribeLocalEvent(OnComponentInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnExamined); } private void OnInteraction(EntityUid uid, ExpCollarComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach || !component.IsHost || args.Target == null || !TryComp(args.Target, out ExpCollarComponent? targetComp) || targetComp.IsHost) return; if (targetComp.Linked.Count != 0 || !targetComp.Virgin) { _popup.PopupEntity(Loc.GetString("expcollar-connected"), args.Target.Value, PopupType.SmallCaution); return; } _popup.PopupEntity(Loc.GetString("expcollar-connect"), args.Target.Value, PopupType.MediumCaution); component.Linked.Add(args.Target.Value); targetComp.Linked.Add(uid); } private async void OnMobStateChanged(EntityUid uid, ExpCollarUserComponent component, MobStateChangedEvent args) { if (component.Tool == null || !(args.OldMobState == MobState.Alive && args.NewMobState != MobState.Alive)) return; if (!TryComp(component.Tool, out var expCollarComponent)) return; if (expCollarComponent.Armed == false || !expCollarComponent.IsHost) return; Destroy(component.Tool.Value); foreach (var linkedCollar in expCollarComponent.Linked) { if (linkedCollar == null) return; _popup.PopupEntity(Loc.GetString("expcollar-kill"), linkedCollar, PopupType.LargeCaution); Destroy(linkedCollar); } } private void OnEquipped(EntityUid uid, ExpCollarComponent component, ClothingGotEquippedEvent args) { if (TryComp(args.Wearer, out _)) return; var comp = EnsureComp(args.Wearer); comp.Tool = uid; component.Wearer = args.Wearer; if (!_mobState.IsAlive(args.Wearer)) return; if (component is { Armed: false, IsHost: false }) { var a = component.Linked.FirstOrDefault(); if (!TryComp(a, out var hostCollarComponent)) return; if (hostCollarComponent.Armed) { component.Armed = true; _popup.PopupEntity(Loc.GetString("expcollar-armed"), uid, PopupType.LargeCaution); } } if (component.IsHost) { component.Armed = true; _tag.AddTag(uid, "CannotSuicide"); _popup.PopupEntity(Loc.GetString("expcollar-armed"), args.Wearer, PopupType.LargeCaution); foreach (var i in component.Linked) { if (!TryComp(i, out var expCollarComponent)) continue; if (expCollarComponent.Wearer == null) continue; expCollarComponent.Armed = true; EnsureComp(i); if (TryComp(i, out var iClothingComponent)) _clothing.SetStripDelay((i, iClothingComponent), TimeSpan.FromSeconds(30)); _popup.PopupEntity(Loc.GetString("expcollar-armed"), i, PopupType.LargeCaution); } } if (component.Armed) { EnsureComp(uid); if (TryComp(uid, out var clothingComponent)) _clothing.SetStripDelay((uid, clothingComponent), TimeSpan.FromSeconds(30)); } } private void OnUnequipped(EntityUid uid, ExpCollarComponent component, ClothingGotUnequippedEvent args) { if (!TryComp(args.Wearer, out var expCollarUserComponent)) return; component.Wearer = null; component.Armed = false; component.Virgin = false; RemComp(args.Wearer); if (HasComp(uid)) RemComp(uid); if (TryComp(uid, out var clothingComponent)) _clothing.SetStripDelay((uid, clothingComponent), TimeSpan.FromSeconds(10)); } private void OnComponentInit(EntityUid uid, ExpCollarComponent component, ComponentInit args) { if (!TryComp(uid, out var clothingComponent)) return; // А вот нехуй в лоадауты такую штуку пихать. Надевать ее надо. if (clothingComponent.InSlot != null) QueueDel(uid); _clothing.SetStripDelay((uid, clothingComponent), component.InitialStripDelay); } private void OnShutdown(EntityUid uid, ExpCollarComponent component, ComponentShutdown args) { if (component.Wearer == null) return; if (!TryComp(component.Wearer, out var expCollarUserComponent)) // На него насильно надели... return; RemComp(component.Wearer.Value); } private async void Destroy(EntityUid uid) { if (!TryComp(uid, out var collar)) return; if (collar.Wearer == null) { // Больше нельзя использовать RemComp(uid); return; } if (collar.Armed == false) return; if (uid == null) return; _popup.PopupEntity(Loc.GetString("expcollar-boom"), uid, PopupType.LargeCaution); _audio.PlayPvs(collar.BeepSound, uid); await Task.Delay(TimeSpan.FromSeconds(1)); for (var i = 10; i > 0; i--) { if (uid == null) return; _popup.PopupEntity(Loc.GetString("expcollar-popup", ("timer", i)), uid, PopupType.LargeCaution); _audio.PlayPvs(collar.BeepSound, uid); await Task.Delay(TimeSpan.FromSeconds(1)); } if (HasComp(collar.Wearer.Value)) { _damageable.TryChangeDamage(collar.Wearer.Value, collar.Damage); _trigger.Trigger(uid); } } private void OnExamined(EntityUid uid, ExpCollarComponent component, ExaminedEvent args) { args.PushMarkup(component.Armed ? Loc.GetString("expcollar-examine-armed") : Loc.GetString("expcoller-examine-disarmed")); if (component.Wearer == null) { args.PushMarkup(component.Virgin ? Loc.GetString("expcollar-examine-virgin") : Loc.GetString("expcollar-examine-unvirgin")); if (component.Linked.Count != 0) { args.PushMarkup(Loc.GetString("expcollar-examine-linked")); } } } }