From d722f837a57275f2a04b3d6f16bf9c506d3af5ba Mon Sep 17 00:00:00 2001 From: nikthechampiongr Date: Mon, 25 Mar 2024 17:45:05 +0200 Subject: [PATCH] Replace the teleportation logic on the SCRAM implant! Now instead of just trying to pick a random tile in range 20 times, the scram teleportation logic now: - Gets a list of grids in range - Until a suitable tile is picked it picks a random grid - From that grid it picks a random tile. - If the tile is suitable, then it is set as the target and the user will be teleported there. - Grids and tiles are randomly picked as outlined above until a valid tile is found, or all valid grids and tiles are exhausted. - Should no suitable tile be found then they get teleported to the same position they are at. Effectively not teleporting them. --- .../Components/ScramImplantComponent.cs | 6 -- .../Implants/SubdermalImplantSystem.cs | 63 +++++++++++++------ 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/Content.Server/Implants/Components/ScramImplantComponent.cs b/Content.Server/Implants/Components/ScramImplantComponent.cs index 88c433abfbe9b8..f3bbc9e584274e 100644 --- a/Content.Server/Implants/Components/ScramImplantComponent.cs +++ b/Content.Server/Implants/Components/ScramImplantComponent.cs @@ -15,12 +15,6 @@ public sealed partial class ScramImplantComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public float TeleportRadius = 100f; - /// - /// How many times to check for a valid tile to teleport to - /// - [DataField, ViewVariables(VVAccess.ReadOnly)] - public int TeleportAttempts = 20; - [DataField, ViewVariables(VVAccess.ReadWrite)] public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg"); } diff --git a/Content.Server/Implants/SubdermalImplantSystem.cs b/Content.Server/Implants/SubdermalImplantSystem.cs index 6b58f6eb0920dd..9c2f180692d5af 100644 --- a/Content.Server/Implants/SubdermalImplantSystem.cs +++ b/Content.Server/Implants/SubdermalImplantSystem.cs @@ -1,4 +1,5 @@ -using Content.Server.Cuffs; +using System.Linq; +using Content.Server.Cuffs; using Content.Server.Forensics; using Content.Server.Humanoid; using Content.Server.Implants.Components; @@ -21,6 +22,7 @@ using System.Numerics; using Content.Shared.Movement.Pulling.Components; using Content.Shared.Movement.Pulling.Systems; +using Robust.Shared.Map.Components; namespace Content.Server.Implants; @@ -37,6 +39,8 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem [Dependency] private readonly SharedTransformSystem _xform = default!; [Dependency] private readonly ForensicsSystem _forensicsSystem = default!; [Dependency] private readonly PullingSystem _pullingSystem = default!; + [Dependency] private readonly EntityLookupSystem _lookupSystem = default!; + [Dependency] private readonly SharedMapSystem _mapSystem = default!; private EntityQuery _physicsQuery; @@ -109,35 +113,54 @@ private void OnScramImplant(EntityUid uid, SubdermalImplantComponent component, var xform = Transform(ent); var entityCoords = xform.Coordinates.ToMap(EntityManager, _xform); - // try to find a valid position to teleport to, teleport to whatever works if we can't - var targetCoords = new MapCoordinates(); - for (var i = 0; i < implant.TeleportAttempts; i++) + var grids = _lookupSystem.GetEntitiesInRange(entityCoords, implant.TeleportRadius).ToList(); + _random.Shuffle(grids); + var targetCoords = entityCoords; // If we somehow fail to find a suitable tile then we essentially we just don't teleport. + + foreach (var grid in grids) { - var distance = implant.TeleportRadius * MathF.Sqrt(_random.NextFloat()); // to get an uniform distribution - targetCoords = entityCoords.Offset(_random.NextAngle().ToVec() * distance); + var valid = false; - // prefer teleporting to grids - if (!_mapManager.TryFindGridAt(targetCoords, out var gridUid, out var grid)) - continue; + var range = (float) Math.Sqrt(implant.TeleportRadius); + var box = Box2.CenteredAround(entityCoords.Position, new Vector2(range, range)); + var tilesInRange = _mapSystem.GetTilesEnumerator(grid.Owner, grid.Comp, box, false); + var tileList = new List(); - // the implant user probably does not want to be in your walls - var valid = true; - foreach (var entity in grid.GetAnchoredEntities(targetCoords)) + while (tilesInRange.MoveNext(out var tile)) { - if (!_physicsQuery.TryGetComponent(entity, out var body)) - continue; + tileList.Add(tile); + } - if (body.BodyType != BodyType.Static || - !body.Hard || - (body.CollisionLayer & (int) CollisionGroup.Impassable) == 0) - continue; + _random.Shuffle(tileList); - valid = false; - break; + foreach (var tile in tileList) + { + valid = true; + foreach(var entity in _mapSystem.GetAnchoredEntities(grid.Owner, grid.Comp, tile.GridIndices)) + { + if (!_physicsQuery.TryGetComponent(entity, out var body)) + continue; + + if (body.BodyType != BodyType.Static || + !body.Hard || + (body.CollisionLayer & (int) CollisionGroup.Impassable) == 0) + continue; + + valid = false; + break; + } + + if (valid) + { + targetCoords = _mapSystem.GridTileToWorld(grid.Owner, grid.Comp, tile.GridIndices); + break; + } } + if (valid) break; } + _xform.SetWorldPosition(ent, targetCoords.Position); _xform.AttachToGridOrMap(ent, xform); _audio.PlayPvs(implant.TeleportSound, ent);