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"));
}
}
}
}