71 lines
3.3 KiB
C#
71 lines
3.3 KiB
C#
using System.Numerics;
|
|
using Content.Server.Xenoarchaeology.Artifact.XAE.Components;
|
|
using Content.Shared.Mind.Components;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.Teleportation.Systems;
|
|
using Content.Shared.Xenoarchaeology.Artifact;
|
|
using Content.Shared.Xenoarchaeology.Artifact.XAE;
|
|
using Robust.Shared.Collections;
|
|
using Robust.Shared.Containers;
|
|
using Robust.Shared.Random;
|
|
using Robust.Shared.Timing;
|
|
using Content.Shared.Tiles; // Frontier
|
|
|
|
namespace Content.Server.Xenoarchaeology.Artifact.XAE;
|
|
|
|
/// <summary>
|
|
/// System for xeno artifact effect that creates temporary portal between places on station.
|
|
/// </summary>
|
|
public sealed class XAEPortalSystem : BaseXAESystem<XAEPortalComponent>
|
|
{
|
|
[Dependency] private readonly IRobustRandom _random = default!;
|
|
[Dependency] private readonly LinkedEntitySystem _link = default!;
|
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
|
[Dependency] private readonly IGameTiming _timing = default!;
|
|
|
|
/// <inheritdoc />
|
|
protected override void OnActivated(Entity<XAEPortalComponent> ent, ref XenoArtifactNodeActivatedEvent args)
|
|
{
|
|
if (!_timing.IsFirstTimePredicted)
|
|
return;
|
|
|
|
var entXform = Transform(ent); // Frontier
|
|
var map = entXform.MapID; // Frontier: Transform(ent)<entXform
|
|
var entPosition = _transform.GetMapCoordinates(ent, entXform).Position; // Frontier
|
|
var validMinds = new ValueList<EntityUid>();
|
|
var mindQuery = EntityQueryEnumerator<MindContainerComponent, MobStateComponent, TransformComponent, MetaDataComponent>();
|
|
while (mindQuery.MoveNext(out var uid, out var mc, out _, out var xform, out var meta))
|
|
{
|
|
// check if the MindContainer has a Mind and if the entity is not in a container (this also auto excludes AI) and if they are on the same map
|
|
if (mc.HasMind && !_container.IsEntityOrParentInContainer(uid, meta: meta, xform: xform) && xform.MapID == map)
|
|
{
|
|
// Frontier: ensure range check (don't teleport people from across the map or off of protected grids)
|
|
if (TryComp(xform.GridUid, out ProtectedGridComponent? grid) && grid.PreventArtifactTriggers)
|
|
continue;
|
|
|
|
if (Vector2.Distance(_transform.GetMapCoordinates(uid, xform).Position, entPosition) > ent.Comp.MaxRange)
|
|
continue;
|
|
// End Frontier: ensure range check (don't teleport people from across the map or off of protected grids)
|
|
|
|
validMinds.Add(uid);
|
|
}
|
|
}
|
|
// this would only be 0 if there were a station full of AIs and no one else, in that case just stop this function
|
|
if (validMinds.Count == 0)
|
|
return;
|
|
|
|
if(!TrySpawnNextTo(ent.Comp.PortalProto, args.Artifact, out var firstPortal))
|
|
return;
|
|
|
|
var target = _random.Pick(validMinds);
|
|
if(!TrySpawnNextTo(ent.Comp.PortalProto, target, out var secondPortal))
|
|
return;
|
|
|
|
// Manual position swapping, because the portal that opens doesn't trigger a collision, and doesn't teleport targets the first time.
|
|
_transform.SwapPositions(target, args.Artifact.Owner);
|
|
|
|
_link.TryLink(firstPortal.Value, secondPortal.Value, true);
|
|
}
|
|
}
|