From 94ef2cb66ecc68486b801400526a763ffd979050 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 21 Jul 2021 19:16:10 +1000 Subject: [PATCH] Nuke portals (#4315) --- Content.Client/Entry/IgnoredComponents.cs | 1 - .../Visualizers/HandTeleporterVisualizer.cs | 34 --- .../Movement/Visualizers/PortalVisualizer.cs | 54 ---- Content.Client/Portal/PortalComponent.cs | 10 - .../Portal/Components/PortalComponent.cs | 165 ------------ .../Portal/Components/TeleporterComponent.cs | 240 ------------------ .../Components/SharedPortalComponent.cs | 37 --- .../Components/SharedTeleporterComponent.cs | 48 ---- .../Entities/Mobs/NPCs/simplemob.yml | 3 - .../Entities/Mobs/Species/human.yml | 1 - Resources/Prototypes/tags.yml | 3 - 11 files changed, 596 deletions(-) delete mode 100644 Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs delete mode 100644 Content.Client/Movement/Visualizers/PortalVisualizer.cs delete mode 100644 Content.Client/Portal/PortalComponent.cs delete mode 100644 Content.Server/Portal/Components/PortalComponent.cs delete mode 100644 Content.Server/Portal/Components/TeleporterComponent.cs delete mode 100644 Content.Shared/Portal/Components/SharedPortalComponent.cs delete mode 100644 Content.Shared/Portal/Components/SharedTeleporterComponent.cs diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 21ed609c74..2042216c68 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -21,7 +21,6 @@ namespace Content.Client.Entry "EmitSoundOnActivate", "FootstepModifier", "HeatResistance", - "ItemTeleporter", "EntityStorage", "Wirecutter", "Screwdriver", diff --git a/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs b/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs deleted file mode 100644 index 597029a37e..0000000000 --- a/Content.Client/Movement/Visualizers/HandTeleporterVisualizer.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using Content.Shared.Portal.Components; -using JetBrains.Annotations; -using Robust.Client.GameObjects; - -namespace Content.Client.Movement.Visualizers -{ - [UsedImplicitly] - public class HandTeleporterVisualizer : AppearanceVisualizer - { - - public override void OnChangeData(AppearanceComponent component) - { - var sprite = component.Owner.GetComponent(); - if (!component.TryGetData(TeleporterVisuals.VisualState, out TeleporterVisualState state)) - { - state = TeleporterVisualState.Ready; - } - - switch (state) - { - case TeleporterVisualState.Charging: - sprite.LayerSetState(0, "charging"); - break; - case TeleporterVisualState.Ready: - sprite.LayerSetState(0, "ready"); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - -} diff --git a/Content.Client/Movement/Visualizers/PortalVisualizer.cs b/Content.Client/Movement/Visualizers/PortalVisualizer.cs deleted file mode 100644 index 4ab0bf605b..0000000000 --- a/Content.Client/Movement/Visualizers/PortalVisualizer.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Content.Shared.Portal.Components; -using JetBrains.Annotations; -using Robust.Client.GameObjects; -using Robust.Shared.GameObjects; - -namespace Content.Client.Movement.Visualizers -{ - [UsedImplicitly] - public class PortalVisualizer : AppearanceVisualizer - { - public override void InitializeEntity(IEntity entity) - { - base.InitializeEntity(entity); - - var sprite = entity.GetComponent(); - - sprite.LayerMapSet(Layers.Portal, sprite.AddLayerState("portal-pending")); - sprite.LayerSetShader(Layers.Portal, "unshaded"); - - } - - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - - var sprite = component.Owner.GetComponent(); - if (component.TryGetData(PortalVisuals.State, out var state)) - { - switch (state) - { - case PortalState.Pending: - sprite.LayerSetState(Layers.Portal, "portal-pending"); - break; - // TODO: Spritework here? - case PortalState.UnableToTeleport: - sprite.LayerSetState(Layers.Portal, "portal-unconnected"); - break; - case PortalState.RecentlyTeleported: - sprite.LayerSetState(Layers.Portal, "portal-unconnected"); - break; - } - } - else - { - sprite.LayerSetState(Layers.Portal, "portal-pending"); - } - } - - enum Layers : byte - { - Portal - } - } -} diff --git a/Content.Client/Portal/PortalComponent.cs b/Content.Client/Portal/PortalComponent.cs deleted file mode 100644 index 7ef2899c32..0000000000 --- a/Content.Client/Portal/PortalComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Content.Shared.Portal.Components; -using Robust.Shared.GameObjects; - -namespace Content.Client.Portal -{ - [RegisterComponent] - public class PortalComponent : SharedPortalComponent - { - } -} diff --git a/Content.Server/Portal/Components/PortalComponent.cs b/Content.Server/Portal/Components/PortalComponent.cs deleted file mode 100644 index 3d7b33bc90..0000000000 --- a/Content.Server/Portal/Components/PortalComponent.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Collections.Generic; -using Content.Shared.Portal.Components; -using Content.Shared.Tag; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.GameObjects; -using Robust.Shared.Physics.Collision; -using Robust.Shared.Physics.Dynamics; -using Robust.Shared.Player; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; - -namespace Content.Server.Portal.Components -{ - [RegisterComponent] - public class PortalComponent : SharedPortalComponent, IStartCollide - { - // Potential improvements: Different sounds, - // Add Gateways - // More efficient form of GetEntitiesIntersecting, - // Put portal above most other things layer-wise - // Add telefragging (get entities on connecting portal and force brute damage) - - private IEntity? _connectingTeleporter; - private PortalState _state = PortalState.Pending; - [ViewVariables(VVAccess.ReadWrite)] [DataField("individual_cooldown")] private float _individualPortalCooldown = 2.1f; - [ViewVariables] [DataField("overall_cooldown")] private float _overallPortalCooldown = 2.0f; - [ViewVariables] private bool _onCooldown; - [ViewVariables] [DataField("departure_sound")] private string _departureSound = "/Audio/Effects/teleport_departure.ogg"; - [ViewVariables] [DataField("arrival_sound")] private string _arrivalSound = "/Audio/Effects/teleport_arrival.ogg"; - public readonly List ImmuneEntities = new(); // K - [ViewVariables(VVAccess.ReadWrite)] [DataField("alive_time")] private float _aliveTime = 10f; - - protected override void OnAdd() - { - // This will blow up an entity it's attached to - base.OnAdd(); - - _state = PortalState.Pending; - - if (_aliveTime > 0) - { - Owner.SpawnTimer(TimeSpan.FromSeconds(_aliveTime), () => Owner.Delete()); - } - } - - public bool CanBeConnected() - { - return _connectingTeleporter == null; - } - - public void TryConnectPortal(IEntity otherPortal) - { - if (otherPortal.TryGetComponent(out var connectedPortal) && connectedPortal.CanBeConnected()) - { - _connectingTeleporter = otherPortal; - connectedPortal._connectingTeleporter = Owner; - TryChangeState(PortalState.Pending); - } - } - - public void TryChangeState(PortalState targetState) - { - if (Deleted) - { - return; - } - - _state = targetState; - - if (Owner.TryGetComponent(out AppearanceComponent? appearance)) - { - appearance.SetData(PortalVisuals.State, _state); - } - } - - private void ReleaseCooldown(IEntity entity) - { - if (Deleted) - { - return; - } - - if (ImmuneEntities.Contains(entity)) - { - ImmuneEntities.Remove(entity); - } - - if (_connectingTeleporter != null && - _connectingTeleporter.TryGetComponent(out var otherPortal)) - { - otherPortal.ImmuneEntities.Remove(entity); - } - } - - private bool IsEntityPortable(IEntity entity) - { - // TODO: Check if it's slotted etc. Otherwise the slot item itself gets ported. - return !ImmuneEntities.Contains(entity) && - entity.HasTag("Teleportable"); - } - - public void StartCooldown() - { - if (_overallPortalCooldown <= 0 || _onCooldown) - { - // Just in case? - _onCooldown = false; - return; - } - - _onCooldown = true; - TryChangeState(PortalState.RecentlyTeleported); - - if (_connectingTeleporter == null || - !_connectingTeleporter.TryGetComponent(out var otherPortal)) - { - return; - } - - otherPortal.TryChangeState(PortalState.RecentlyTeleported); - - Owner.SpawnTimer(TimeSpan.FromSeconds(_overallPortalCooldown), () => - { - _onCooldown = false; - TryChangeState(PortalState.Pending); - otherPortal.TryChangeState(PortalState.Pending); - }); - } - - public void TryPortalEntity(IEntity entity) - { - if (ImmuneEntities.Contains(entity) || - _connectingTeleporter == null || - !IsEntityPortable(entity)) - { - return; - } - - var position = _connectingTeleporter.Transform.Coordinates; - - // Departure - // Do we need to rate-limit sounds to stop ear BLAST? - SoundSystem.Play(Filter.Pvs(entity), _departureSound, entity.Transform.Coordinates); - entity.Transform.Coordinates = position; - SoundSystem.Play(Filter.Pvs(entity), _arrivalSound, entity.Transform.Coordinates); - TryChangeState(PortalState.RecentlyTeleported); - - // To stop spam teleporting. Could potentially look at adding a timer to flush this from the portal - ImmuneEntities.Add(entity); - _connectingTeleporter.GetComponent().ImmuneEntities.Add(entity); - Owner.SpawnTimer(TimeSpan.FromSeconds(_individualPortalCooldown), () => ReleaseCooldown(entity)); - StartCooldown(); - } - - void IStartCollide.CollideWith(Fixture ourFixture, Fixture otherFixture, in Manifold manifold) - { - if (_onCooldown == false) - { - TryPortalEntity(otherFixture.Body.Owner); - } - } - } -} diff --git a/Content.Server/Portal/Components/TeleporterComponent.cs b/Content.Server/Portal/Components/TeleporterComponent.cs deleted file mode 100644 index 4101e6fd16..0000000000 --- a/Content.Server/Portal/Components/TeleporterComponent.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Content.Shared.Interaction; -using Content.Shared.Portal.Components; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; -using Robust.Shared.Physics; -using Robust.Shared.Player; -using Robust.Shared.Random; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; - -namespace Content.Server.Portal.Components -{ - [RegisterComponent] - public class TeleporterComponent : Component, IAfterInteract - { - [Dependency] private readonly IServerEntityManager _serverEntityManager = default!; - [Dependency] private readonly IRobustRandom _spreadRandom = default!; - - // TODO: Look at MapManager.Map for Beacons to get all entities on grid - public ItemTeleporterState State => _state; - - public override string Name => "ItemTeleporter"; - - [DataField("charge_time")] - [ViewVariables] private float _chargeTime = 0.2f; - [DataField("cooldown")] - [ViewVariables] private float _cooldown = 2f; - [DataField("range")] - [ViewVariables] private int _range = 15; - [ViewVariables] private ItemTeleporterState _state; - [DataField("teleporter_type")] - [ViewVariables] private TeleporterType _teleporterType = TeleporterType.Random; - [ViewVariables] [DataField("departure_sound")] private string _departureSound = "/Audio/Effects/teleport_departure.ogg"; - [ViewVariables] [DataField("arrival_sound")] private string _arrivalSound = "/Audio/Effects/teleport_arrival.ogg"; - [ViewVariables] [DataField("cooldown_sound")] private string? _cooldownSound = default; - // If the direct OR random teleport will try to avoid hitting collidables - [DataField("avoid_walls")] [ViewVariables] - private bool _avoidCollidable = true; - [DataField("portal_alive_time")] - [ViewVariables] private float _portalAliveTime = 5f; - - private void SetState(ItemTeleporterState newState) - { - if (!Owner.TryGetComponent(out AppearanceComponent? appearance)) - { - return; - } - - if (newState == ItemTeleporterState.Cooldown) - { - appearance.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Charging); - } - else - { - appearance.SetData(TeleporterVisuals.VisualState, TeleporterVisualState.Ready); - } - _state = newState; - } - - async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) - { - if (_teleporterType == TeleporterType.Directed) - { - TryDirectedTeleport(eventArgs.User, eventArgs.ClickLocation.ToMap(Owner.EntityManager)); - } - - if (_teleporterType == TeleporterType.Random) - { - TryRandomTeleport(eventArgs.User); - } - - return true; - } - - public void TryDirectedTeleport(IEntity user, MapCoordinates mapCoords) - { - // Checks - if ((user.Transform.WorldPosition - mapCoords.Position).LengthSquared > _range * _range) - { - return; - } - - if (_state == ItemTeleporterState.On) - { - return; - } - if (_avoidCollidable) - { - foreach (var entity in IoCManager.Resolve().GetEntitiesIntersecting(mapCoords)) - { - // Added this component to avoid stacking portals and causing shenanigans - // TODO: Doesn't do a great job of stopping stacking portals for directed - if (entity.HasComponent() || entity.HasComponent()) - { - return; - } - } - } - // Start / Continue - if (_state == ItemTeleporterState.Off) - { - SetState(ItemTeleporterState.Charging); - // Play charging sound here if you want - } - - if (_state != ItemTeleporterState.Charging) - { - return; - } - - Owner.SpawnTimer(TimeSpan.FromSeconds(_chargeTime), () => Teleport(user, mapCoords.Position)); - StartCooldown(); - } - - public void StartCooldown() - { - SetState(ItemTeleporterState.Cooldown); - Owner.SpawnTimer(TimeSpan.FromSeconds(_chargeTime + _cooldown), () => SetState(ItemTeleporterState.Off)); - if (_cooldownSound != null) - { - SoundSystem.Play(Filter.Pvs(Owner), _cooldownSound, Owner); - } - } - - protected override void Initialize() - { - base.Initialize(); - _state = ItemTeleporterState.Off; - } - - private bool EmptySpace(IEntity user, Vector2 target) - { - // TODO: Check the user's spot? Upside is no stacking TPs but downside is they can't unstuck themselves from walls. - foreach (var entity in IoCManager.Resolve().GetEntitiesIntersecting(user.Transform.MapID, target)) - { - if (entity.HasComponent() || entity.HasComponent()) - { - return false; - } - } - return true; - } - - private Vector2 RandomEmptySpot(IEntity user, int range) - { - Vector2 targetVector = user.Transform.Coordinates.Position; - // Definitely a better way to do this - foreach (var i in Enumerable.Range(0, 5)) - { - var randomRange = _spreadRandom.Next(0, range); - var angle = Angle.FromDegrees(_spreadRandom.Next(0, 359)); - targetVector = user.Transform.Coordinates.Position + angle.ToVec() * randomRange; - if (EmptySpace(user, targetVector)) - { - return targetVector; - } - if (i == 19) - { - return targetVector; - } - } - - return targetVector; - } - - public void TryRandomTeleport(IEntity user) - { - // Checks - if (_state == ItemTeleporterState.On) - { - return; - } - - Vector2 targetVector; - if (_avoidCollidable) - { - targetVector = RandomEmptySpot(user, _range); - } - else - { - var randomRange = _spreadRandom.Next(0, _range); - var angle = Angle.FromDegrees(_spreadRandom.Next(0, 359)); - targetVector = user.Transform.Coordinates.Position + angle.ToVec() * randomRange; - } - // Start / Continue - if (_state == ItemTeleporterState.Off) - { - SetState(ItemTeleporterState.Charging); - } - - if (_state != ItemTeleporterState.Charging) - { - return; - } - - // Seemed easier to just start the cd timer at the same time - Owner.SpawnTimer(TimeSpan.FromSeconds(_chargeTime), () => Teleport(user, targetVector)); - StartCooldown(); - } - - public void Teleport(IEntity user, Vector2 vector) - { - // Messy maybe? - var targetGrid = user.Transform.Coordinates.WithPosition(vector); - - // If portals use those, otherwise just move em over - if (_portalAliveTime > 0.0f) - { - // Call Delete here as the teleporter should have control over portal longevity - // Departure portal - var departurePortal = _serverEntityManager.SpawnEntity("Portal", user.Transform.Coordinates); - - // Arrival portal - var arrivalPortal = _serverEntityManager.SpawnEntity("Portal", targetGrid); - if (arrivalPortal.TryGetComponent(out var arrivalComponent)) - { - // Connect. - arrivalComponent.TryConnectPortal(departurePortal); - } - } - else - { - // Departure - SoundSystem.Play(Filter.Pvs(user), _departureSound, user.Transform.Coordinates); - - // Arrival - user.Transform.AttachToGridOrMap(); - user.Transform.WorldPosition = vector; - SoundSystem.Play(Filter.Pvs(user), _arrivalSound, user.Transform.Coordinates); - } - } - } -} diff --git a/Content.Shared/Portal/Components/SharedPortalComponent.cs b/Content.Shared/Portal/Components/SharedPortalComponent.cs deleted file mode 100644 index 766718f7e9..0000000000 --- a/Content.Shared/Portal/Components/SharedPortalComponent.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using Robust.Shared.GameObjects; -using Robust.Shared.Physics; -using Robust.Shared.Serialization; - -namespace Content.Shared.Portal.Components -{ - public abstract class SharedPortalComponent : Component - { - public override string Name => "Portal"; - - protected override void OnAdd() - { - base.OnAdd(); - - if (Owner.TryGetComponent(out var physics)) - { - physics.Hard = false; - } - } - } - - [Serializable, NetSerializable] - public enum PortalVisuals - { - State - } - - [Serializable, NetSerializable] - public enum PortalState - { - RecentlyTeleported, - Pending, - UnableToTeleport, - } - -} diff --git a/Content.Shared/Portal/Components/SharedTeleporterComponent.cs b/Content.Shared/Portal/Components/SharedTeleporterComponent.cs deleted file mode 100644 index 9758501c74..0000000000 --- a/Content.Shared/Portal/Components/SharedTeleporterComponent.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Serialization; - -namespace Content.Shared.Portal.Components -{ - public enum ItemTeleporterState - { - Off, - Charging, - On, - Cooldown, - } - - public enum TeleporterType - { - Directed, - Random, - Beacon, - } - - [NetSerializable] - [Serializable] - public enum TeleporterVisuals - { - VisualState, - } - - [NetSerializable] - [Serializable] - public enum TeleporterVisualState - { - Ready, - Charging, - } - - [Serializable, NetSerializable] - public class TeleportMessage : ComponentMessage - { - public readonly EntityCoordinates Target; - - public TeleportMessage(EntityCoordinates target) - { - Target = target; - } - } -} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 7af3c4fe8e..cef117e5da 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -4,9 +4,6 @@ id: SimpleMobBase suffix: AI components: - - type: Tag - tags: - - Teleportable - type: Reactive reactions: - !type:ExtinguishReaction diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index e4ee7b4b08..05050eda89 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -8,7 +8,6 @@ components: - type: Tag tags: - - Teleportable - FootstepSound - type: Reactive reactions: diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 793b0de8e1..2cb5cdc7b3 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -43,9 +43,6 @@ - type: Tag id: Shovel -- type: Tag - id: Teleportable - - type: Tag id: Wall