| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- using Content.Shared.Examine;
- using Content.Shared.IdentityManagement;
- using Content.Shared.Interaction;
- using Content.Shared.Popups;
- using Content.Shared.Teleportation.Components;
- using Content.Shared.Verbs;
- using Content.Shared.Whitelist;
- using Robust.Shared.Audio.Systems;
- using Robust.Shared.Containers;
- using Robust.Shared.Map.Components;
- using Robust.Shared.Physics;
- using Robust.Shared.Physics.Components;
- using Robust.Shared.Timing;
- namespace Content.Shared.Teleportation.Systems;
- /// <summary>
- /// This handles <see cref="SwapTeleporterComponent"/>
- /// </summary>
- public sealed class SwapTeleporterSystem : EntitySystem
- {
- [Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- [Dependency] private readonly SharedContainerSystem _container = default!;
- [Dependency] private readonly SharedPopupSystem _popup = default!;
- [Dependency] private readonly SharedTransformSystem _transform = default!;
- [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
- private EntityQuery<TransformComponent> _xformQuery;
- /// <inheritdoc/>
- public override void Initialize()
- {
- SubscribeLocalEvent<SwapTeleporterComponent, AfterInteractEvent>(OnInteract);
- SubscribeLocalEvent<SwapTeleporterComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAltVerb);
- SubscribeLocalEvent<SwapTeleporterComponent, ActivateInWorldEvent>(OnActivateInWorld);
- SubscribeLocalEvent<SwapTeleporterComponent, ExaminedEvent>(OnExamined);
- SubscribeLocalEvent<SwapTeleporterComponent, ComponentShutdown>(OnShutdown);
- _xformQuery = GetEntityQuery<TransformComponent>();
- }
- private void OnInteract(Entity<SwapTeleporterComponent> ent, ref AfterInteractEvent args)
- {
- var (uid, comp) = ent;
- if (args.Target == null || !args.CanReach)
- return;
- var target = args.Target.Value;
- if (!TryComp<SwapTeleporterComponent>(target, out var targetComp))
- return;
- if (_whitelistSystem.IsWhitelistFail(comp.TeleporterWhitelist, target) ||
- _whitelistSystem.IsWhitelistFail(targetComp.TeleporterWhitelist, uid))
- {
- return;
- }
- if (comp.LinkedEnt != null)
- {
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-link-fail-already"), uid, args.User);
- return;
- }
- if (targetComp.LinkedEnt != null)
- {
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-link-fail-already-other"), uid, args.User);
- return;
- }
- comp.LinkedEnt = target;
- targetComp.LinkedEnt = uid;
- Dirty(uid, comp);
- Dirty(target, targetComp);
- _appearance.SetData(uid, SwapTeleporterVisuals.Linked, true);
- _appearance.SetData(target, SwapTeleporterVisuals.Linked, true);
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-link-create"), uid, args.User);
- }
- private void OnGetAltVerb(Entity<SwapTeleporterComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
- {
- var (uid, comp) = ent;
- if (!args.CanAccess || !args.CanInteract || args.Hands == null || comp.TeleportTime != null)
- return;
- if (!TryComp<SwapTeleporterComponent>(comp.LinkedEnt, out var otherComp) || otherComp.TeleportTime != null)
- return;
- var user = args.User;
- args.Verbs.Add(new AlternativeVerb
- {
- Text = Loc.GetString("swap-teleporter-verb-destroy-link"),
- Priority = 1,
- Act = () =>
- {
- DestroyLink((uid, comp), user);
- }
- });
- }
- private void OnActivateInWorld(Entity<SwapTeleporterComponent> ent, ref ActivateInWorldEvent args)
- {
- if (args.Handled || !args.Complex)
- return;
- var (uid, comp) = ent;
- var user = args.User;
- if (comp.TeleportTime != null)
- return;
- if (comp.LinkedEnt == null)
- {
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-teleport-cancel-link"), ent, user);
- return;
- }
- // don't allow teleporting to happen if the linked one is already teleporting
- if (!TryComp<SwapTeleporterComponent>(comp.LinkedEnt, out var otherComp)
- || otherComp.TeleportTime != null)
- {
- return;
- }
- if (_timing.CurTime < comp.NextTeleportUse)
- {
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-teleport-cancel-time"), ent, user);
- return;
- }
- _audio.PlayPredicted(comp.TeleportSound, uid, user);
- _audio.PlayPredicted(otherComp.TeleportSound, comp.LinkedEnt.Value, user);
- comp.NextTeleportUse = _timing.CurTime + comp.Cooldown;
- comp.TeleportTime = _timing.CurTime + comp.TeleportDelay;
- Dirty(uid, comp);
- args.Handled = true;
- }
- public void DoTeleport(Entity<SwapTeleporterComponent, TransformComponent> ent)
- {
- var (uid, comp, xform) = ent;
- comp.TeleportTime = null;
- Dirty(uid, comp);
- if (comp.LinkedEnt is not { } linkedEnt)
- {
- return;
- }
- var teleEnt = GetTeleportingEntity((uid, xform));
- var otherTeleEnt = GetTeleportingEntity((linkedEnt, Transform(linkedEnt)));
- _container.TryGetOuterContainer(teleEnt, Transform(teleEnt), out var cont);
- _container.TryGetOuterContainer(otherTeleEnt, Transform(otherTeleEnt), out var otherCont);
- if (otherCont != null && !_container.CanInsert(teleEnt, otherCont) ||
- cont != null && !_container.CanInsert(otherTeleEnt, cont))
- {
- _popup.PopupEntity(Loc.GetString("swap-teleporter-popup-teleport-fail",
- ("entity", Identity.Entity(linkedEnt, EntityManager))),
- teleEnt,
- teleEnt,
- PopupType.MediumCaution);
- return;
- }
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-teleport-other",
- ("entity", Identity.Entity(linkedEnt, EntityManager))),
- teleEnt,
- otherTeleEnt,
- PopupType.MediumCaution);
- _transform.SwapPositions(teleEnt, otherTeleEnt);
- }
- /// <remarks>
- /// HYAH -link
- /// </remarks>
- public void DestroyLink(Entity<SwapTeleporterComponent?> ent, EntityUid? user)
- {
- if (!Resolve(ent, ref ent.Comp, false))
- return;
- var linkedNullable = ent.Comp.LinkedEnt;
- ent.Comp.LinkedEnt = null;
- ent.Comp.TeleportTime = null;
- _appearance.SetData(ent, SwapTeleporterVisuals.Linked, false);
- Dirty(ent, ent.Comp);
- if (user != null)
- _popup.PopupClient(Loc.GetString("swap-teleporter-popup-link-destroyed"), ent, user.Value);
- else
- _popup.PopupEntity(Loc.GetString("swap-teleporter-popup-link-destroyed"), ent);
- if (linkedNullable is {} linked)
- DestroyLink(linked, user); // the linked one is shown globally
- }
- private EntityUid GetTeleportingEntity(Entity<TransformComponent> ent)
- {
- var parent = ent.Comp.ParentUid;
- if (HasComp<MapGridComponent>(parent) || HasComp<MapComponent>(parent))
- return ent;
- if (!_xformQuery.TryGetComponent(parent, out var parentXform) || parentXform.Anchored)
- return ent;
- if (!TryComp<PhysicsComponent>(parent, out var body) || body.BodyType == BodyType.Static)
- return ent;
- return GetTeleportingEntity((parent, parentXform));
- }
- private void OnExamined(Entity<SwapTeleporterComponent> ent, ref ExaminedEvent args)
- {
- var (_, comp) = ent;
- using (args.PushGroup(nameof(SwapTeleporterComponent)))
- {
- var locale = comp.LinkedEnt == null
- ? "swap-teleporter-examine-link-absent"
- : "swap-teleporter-examine-link-present";
- args.PushMarkup(Loc.GetString(locale));
- if (_timing.CurTime < comp.NextTeleportUse)
- {
- args.PushMarkup(Loc.GetString("swap-teleporter-examine-time-remaining",
- ("second", (int) ((comp.NextTeleportUse - _timing.CurTime).TotalSeconds + 0.5f))));
- }
- }
- }
- private void OnShutdown(Entity<SwapTeleporterComponent> ent, ref ComponentShutdown args)
- {
- DestroyLink((ent, ent), null);
- }
- public override void Update(float frameTime)
- {
- base.Update(frameTime);
- var query = EntityQueryEnumerator<SwapTeleporterComponent, TransformComponent>();
- while (query.MoveNext(out var uid, out var comp, out var xform))
- {
- if (comp.TeleportTime == null)
- continue;
- if (_timing.CurTime < comp.TeleportTime)
- continue;
- DoTeleport((uid, comp, xform));
- }
- }
- }
|