From 0a394d4af5b3b5320a011ae2bbe0542f41fe22dc Mon Sep 17 00:00:00 2001
From: keronshb <54602815+keronshb@users.noreply.github.com>
Date: Mon, 28 Apr 2025 13:42:24 -0400
Subject: [PATCH] Wizard Teleport Scroll (Teleport Location ECS) (#36424)
---
Content.Benchmarks/PvsBenchmark.cs | 1 +
.../Teleportation/TeleportLocationsSystem.cs | 11 +
.../Ui/TeleportLocationsBoundUserInterface.cs | 36 ++++
.../Teleportation/Ui/TeleportMenu.xaml | 10 +
.../Teleportation/Ui/TeleportMenu.xaml.cs | 74 +++++++
.../Administration/Commands/WarpCommand.cs | 1 +
Content.Server/Ghost/GhostSystem.cs | 1 +
.../Systems/NinjaConditionsSystem.cs | 1 +
Content.Server/Pinpointer/NavMapSystem.cs | 1 +
.../Teleportation/TeleportLocationsSystem.cs | 71 +++++++
Content.Server/Warps/WarpPointComponent.cs | 18 --
Content.Server/Warps/WarpPointSystem.cs | 1 +
.../Components/TeleportLocationsComponent.cs | 66 ++++++
.../Systems/SharedTeleportLocationsSystem.cs | 59 ++++++
.../Teleportation/TeleportLocationsUi.cs | 19 ++
Content.Shared/Warps/WarpPointComponent.cs | 27 +++
.../teleportation/teleportation-menu-gui.ftl | 6 +
Resources/Maps/centcomm.yml | 194 +++++++++---------
.../Catalog/Fills/Lockers/suit_storage.yml | 5 +-
.../Entities/Markers/warp_point.yml | 22 ++
.../Entities/Mobs/Player/narsie.yml | 6 +
.../Entities/Mobs/Player/ratvar.yml | 6 +
.../Entities/Mobs/Player/silicon.yml | 18 ++
.../Objects/Devices/station_beacon.yml | 47 +++++
.../Entities/Objects/Fun/immovable_rod.yml | 3 +
.../Entities/Objects/Misc/dat_fukken_disk.yml | 4 +
.../Entities/Objects/Power/powersink.yml | 6 +
.../Entities/Structures/Machines/nuke.yml | 6 +
.../Generation/Singularity/singularity.yml | 6 +
.../Power/Generation/Tesla/energyball.yml | 6 +
.../Prototypes/Magic/teleport_scroll.yml | 26 +++
.../Roles/Jobs/Fun/wizard_startinggear.yml | 8 +-
Resources/Prototypes/tags.yml | 4 +
33 files changed, 645 insertions(+), 125 deletions(-)
create mode 100644 Content.Client/Teleportation/TeleportLocationsSystem.cs
create mode 100644 Content.Client/Teleportation/Ui/TeleportLocationsBoundUserInterface.cs
create mode 100644 Content.Client/Teleportation/Ui/TeleportMenu.xaml
create mode 100644 Content.Client/Teleportation/Ui/TeleportMenu.xaml.cs
create mode 100644 Content.Server/Teleportation/TeleportLocationsSystem.cs
delete mode 100644 Content.Server/Warps/WarpPointComponent.cs
create mode 100644 Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs
create mode 100644 Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs
create mode 100644 Content.Shared/Teleportation/TeleportLocationsUi.cs
create mode 100644 Content.Shared/Warps/WarpPointComponent.cs
create mode 100644 Resources/Locale/en-US/teleportation/teleportation-menu-gui.ftl
create mode 100644 Resources/Prototypes/Magic/teleport_scroll.yml
diff --git a/Content.Benchmarks/PvsBenchmark.cs b/Content.Benchmarks/PvsBenchmark.cs
index 2f87545426..1edbcb6448 100644
--- a/Content.Benchmarks/PvsBenchmark.cs
+++ b/Content.Benchmarks/PvsBenchmark.cs
@@ -7,6 +7,7 @@ using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
using Content.Server.Mind;
using Content.Server.Warps;
+using Content.Shared.Warps;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.EntitySerialization;
diff --git a/Content.Client/Teleportation/TeleportLocationsSystem.cs b/Content.Client/Teleportation/TeleportLocationsSystem.cs
new file mode 100644
index 0000000000..d191b8d385
--- /dev/null
+++ b/Content.Client/Teleportation/TeleportLocationsSystem.cs
@@ -0,0 +1,11 @@
+using Content.Shared.Teleportation.Systems;
+
+namespace Content.Client.Teleportation;
+
+///
+///
+///
+public sealed partial class TeleportLocationsSystem : SharedTeleportLocationsSystem
+{
+
+}
diff --git a/Content.Client/Teleportation/Ui/TeleportLocationsBoundUserInterface.cs b/Content.Client/Teleportation/Ui/TeleportLocationsBoundUserInterface.cs
new file mode 100644
index 0000000000..80b4f30094
--- /dev/null
+++ b/Content.Client/Teleportation/Ui/TeleportLocationsBoundUserInterface.cs
@@ -0,0 +1,36 @@
+using Content.Shared.Teleportation;
+using Content.Shared.Teleportation.Components;
+using JetBrains.Annotations;
+using Robust.Client.UserInterface;
+
+namespace Content.Client.Teleportation.Ui;
+
+[UsedImplicitly]
+public sealed class TeleportLocationsBoundUserInterface : BoundUserInterface
+{
+ [ViewVariables]
+ private TeleportMenu? _menu;
+
+ public TeleportLocationsBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+ {
+ }
+
+ protected override void Open()
+ {
+ base.Open();
+
+ _menu = this.CreateWindow();
+
+ if (!EntMan.TryGetComponent(Owner, out var teleComp))
+ return;
+
+ _menu.Title = Loc.GetString(teleComp.Name);
+ _menu.Warps = teleComp.AvailableWarps;
+ _menu.AddTeleportButtons();
+
+ _menu.TeleportClicked += (netEnt, pointName) =>
+ {
+ SendPredictedMessage(new TeleportLocationDestinationMessage(netEnt, pointName));
+ };
+ }
+}
diff --git a/Content.Client/Teleportation/Ui/TeleportMenu.xaml b/Content.Client/Teleportation/Ui/TeleportMenu.xaml
new file mode 100644
index 0000000000..50a77bbbcc
--- /dev/null
+++ b/Content.Client/Teleportation/Ui/TeleportMenu.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Teleportation/Ui/TeleportMenu.xaml.cs b/Content.Client/Teleportation/Ui/TeleportMenu.xaml.cs
new file mode 100644
index 0000000000..1a730bf747
--- /dev/null
+++ b/Content.Client/Teleportation/Ui/TeleportMenu.xaml.cs
@@ -0,0 +1,74 @@
+using System.Numerics;
+using Content.Shared.Teleportation.Components;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Client.UserInterface.Controls;
+
+namespace Content.Client.Teleportation.Ui;
+
+[GenerateTypedNameReferences]
+public sealed partial class TeleportMenu : DefaultWindow
+{
+ public string SearchText = "";
+
+ public HashSet Warps = new();
+
+ public event Action? TeleportClicked;
+
+ public TeleportMenu()
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ SearchBar.OnTextChanged += OnSearchTextChanged;
+ }
+
+ public void AddTeleportButtons()
+ {
+ foreach (var points in Warps)
+ {
+ var name = points.Location;
+ var teleportPoint = points.TelePoint;
+
+ var currentButtonRef = new Button
+ {
+ Text = name,
+ TextAlign = Label.AlignMode.Right,
+ HorizontalAlignment = HAlignment.Center,
+ VerticalAlignment = VAlignment.Center,
+ SizeFlagsStretchRatio = 1,
+ MinSize = new Vector2(340, 20),
+ ClipText = true,
+ };
+
+ currentButtonRef.OnPressed += _ => TeleportClicked?.Invoke(teleportPoint, name);
+ currentButtonRef.Visible = ButtonIsVisible(currentButtonRef);
+
+ TeleportButtonContainer.AddChild(currentButtonRef);
+ }
+ }
+
+ private bool ButtonIsVisible(Button button)
+ {
+ return string.IsNullOrEmpty(SearchText) || button.Text == null ||
+ button.Text.Contains(SearchText, StringComparison.OrdinalIgnoreCase);
+ }
+
+ private void UpdateVisibleButtons()
+ {
+ foreach (var child in TeleportButtonContainer.Children)
+ {
+ if (child is Button button)
+ button.Visible = ButtonIsVisible(button);
+ }
+ }
+
+ public void OnSearchTextChanged(LineEdit.LineEditEventArgs args)
+ {
+ SearchText = args.Text;
+ UpdateVisibleButtons();
+ // Very funny it's called TeleportScroll
+ TeleportScroll.SetScrollValue(Vector2.Zero);
+ }
+}
diff --git a/Content.Server/Administration/Commands/WarpCommand.cs b/Content.Server/Administration/Commands/WarpCommand.cs
index afc42c7e19..06d771ec2f 100644
--- a/Content.Server/Administration/Commands/WarpCommand.cs
+++ b/Content.Server/Administration/Commands/WarpCommand.cs
@@ -4,6 +4,7 @@ using Content.Server.Warps;
using Content.Shared.Administration;
using Content.Shared.Follower;
using Content.Shared.Ghost;
+using Content.Shared.Warps;
using Robust.Shared.Console;
using Robust.Shared.Enums;
using Robust.Shared.Map;
diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs
index 8596927b28..ac0455c9a7 100644
--- a/Content.Server/Ghost/GhostSystem.cs
+++ b/Content.Server/Ghost/GhostSystem.cs
@@ -28,6 +28,7 @@ using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Storage.Components;
using Content.Shared.Tag;
+using Content.Shared.Warps;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Configuration;
diff --git a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs
index ee99658f66..808829f6d9 100644
--- a/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs
+++ b/Content.Server/Objectives/Systems/NinjaConditionsSystem.cs
@@ -4,6 +4,7 @@ using Content.Server.Warps;
using Content.Shared.Objectives.Components;
using Content.Shared.Ninja.Components;
using Content.Shared.Roles;
+using Content.Shared.Warps;
using Robust.Shared.Random;
namespace Content.Server.Objectives.Systems;
diff --git a/Content.Server/Pinpointer/NavMapSystem.cs b/Content.Server/Pinpointer/NavMapSystem.cs
index 3ab0e8eff1..2819f5ba42 100644
--- a/Content.Server/Pinpointer/NavMapSystem.cs
+++ b/Content.Server/Pinpointer/NavMapSystem.cs
@@ -13,6 +13,7 @@ using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
using System.Diagnostics.CodeAnalysis;
+using Content.Shared.Warps;
namespace Content.Server.Pinpointer;
diff --git a/Content.Server/Teleportation/TeleportLocationsSystem.cs b/Content.Server/Teleportation/TeleportLocationsSystem.cs
new file mode 100644
index 0000000000..14211d9672
--- /dev/null
+++ b/Content.Server/Teleportation/TeleportLocationsSystem.cs
@@ -0,0 +1,71 @@
+using Content.Server.Chat.Systems;
+using Content.Shared.Teleportation;
+using Content.Shared.Teleportation.Components;
+using Content.Shared.Teleportation.Systems;
+using Content.Shared.UserInterface;
+using Content.Shared.Warps;
+using Content.Shared.Whitelist;
+
+namespace Content.Server.Teleportation;
+
+///
+///
+///
+public sealed partial class TeleportLocationsSystem : SharedTeleportLocationsSystem
+{
+ [Dependency] private readonly ChatSystem _chat = default!;
+ [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnMapInit);
+ SubscribeLocalEvent(OnBeforeUiOpen);
+ }
+
+ private void OnMapInit(Entity ent, ref MapInitEvent args)
+ {
+ UpdateTeleportPoints(ent);
+ }
+
+ private void OnBeforeUiOpen(Entity ent, ref BeforeActivatableUIOpenEvent args)
+ {
+ UpdateTeleportPoints(ent);
+ }
+
+ protected override void OnTeleportToLocationRequest(Entity ent, ref TeleportLocationDestinationMessage args)
+ {
+ if (Delay.IsDelayed(ent.Owner, TeleportDelay))
+ return;
+
+ if (!string.IsNullOrWhiteSpace(ent.Comp.Speech))
+ {
+ var msg = Loc.GetString(ent.Comp.Speech, ("location", args.PointName));
+ _chat.TrySendInGameICMessage(args.Actor, msg, InGameICChatType.Speak, ChatTransmitRange.Normal);
+ }
+
+ base.OnTeleportToLocationRequest(ent, ref args);
+ }
+
+ // If it's in shared this doesn't populate the points on the UI
+ ///
+ /// Gets the teleport points to send to the BUI
+ ///
+ private void UpdateTeleportPoints(Entity ent)
+ {
+ ent.Comp.AvailableWarps.Clear();
+
+ var allEnts = AllEntityQuery();
+
+ while (allEnts.MoveNext(out var warpEnt, out var warpPointComp))
+ {
+ if (_whitelist.IsBlacklistPass(warpPointComp.Blacklist, warpEnt) || string.IsNullOrWhiteSpace(warpPointComp.Location))
+ continue;
+
+ ent.Comp.AvailableWarps.Add(new TeleportPoint(warpPointComp.Location, GetNetEntity(warpEnt)));
+ }
+
+ Dirty(ent);
+ }
+}
diff --git a/Content.Server/Warps/WarpPointComponent.cs b/Content.Server/Warps/WarpPointComponent.cs
deleted file mode 100644
index ce169f2e19..0000000000
--- a/Content.Server/Warps/WarpPointComponent.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Content.Server.Warps
-{
- ///
- /// Allows ghosts etc to warp to this entity by name.
- ///
- [RegisterComponent]
- public sealed partial class WarpPointComponent : Component
- {
- [ViewVariables(VVAccess.ReadWrite), DataField]
- public string? Location;
-
- ///
- /// If true, ghosts warping to this entity will begin following it.
- ///
- [DataField]
- public bool Follow;
- }
-}
diff --git a/Content.Server/Warps/WarpPointSystem.cs b/Content.Server/Warps/WarpPointSystem.cs
index d3b978a147..2e2264a81a 100644
--- a/Content.Server/Warps/WarpPointSystem.cs
+++ b/Content.Server/Warps/WarpPointSystem.cs
@@ -1,5 +1,6 @@
using Content.Shared.Examine;
using Content.Shared.Ghost;
+using Content.Shared.Warps;
namespace Content.Server.Warps;
diff --git a/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs b/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs
new file mode 100644
index 0000000000..ef5d6c5b2c
--- /dev/null
+++ b/Content.Shared/Teleportation/Components/TeleportLocationsComponent.cs
@@ -0,0 +1,66 @@
+using Content.Shared.Teleportation.Systems;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Teleportation.Components;
+
+// TODO: In the future assimilate ghost UI to use this.
+///
+/// Used where you want an entity to display a list of player-safe teleport locations
+/// They teleport to the location clicked
+/// Looks for non Ghost-Only WarpPointComponents
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedTeleportLocationsSystem)), AutoGenerateComponentState]
+public sealed partial class TeleportLocationsComponent : Component
+{
+ ///
+ /// List of available warp points
+ ///
+ [DataField, AutoNetworkedField]
+ public HashSet AvailableWarps = new();
+
+ ///
+ /// What should spawn as an effect when the user teleports?
+ ///
+ [DataField]
+ public EntProtoId? TeleportEffect;
+
+ ///
+ /// Should this close the BUI after teleport?
+ ///
+ [DataField]
+ public bool CloseAfterTeleport;
+
+ ///
+ /// Name of the Teleport Location menu
+ ///
+ [DataField]
+ public LocId Name;
+
+ ///
+ /// Should the user have some speech if they teleport?
+ /// If enabled it will be prepended to the location name.
+ /// So something like "I am going to" would become "I am going to (Bridge)"
+ ///
+ [DataField]
+ public LocId? Speech;
+}
+
+///
+/// A teleport point, which has a location (the destination) and the entity that it represents.
+///
+[Serializable, NetSerializable, DataDefinition]
+public partial record struct TeleportPoint
+{
+ [DataField]
+ public string Location;
+ [DataField]
+ public NetEntity TelePoint;
+
+ public TeleportPoint(string Location, NetEntity TelePoint)
+ {
+ this.Location = Location;
+ this.TelePoint = TelePoint;
+ }
+}
diff --git a/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs b/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs
new file mode 100644
index 0000000000..eb4be36ced
--- /dev/null
+++ b/Content.Shared/Teleportation/Systems/SharedTeleportLocationsSystem.cs
@@ -0,0 +1,59 @@
+using Content.Shared.Teleportation.Components;
+using Content.Shared.Timing;
+using Content.Shared.UserInterface;
+using Content.Shared.Warps;
+
+namespace Content.Shared.Teleportation.Systems;
+
+///
+///
+///
+public abstract partial class SharedTeleportLocationsSystem : EntitySystem
+{
+ [Dependency] protected readonly UseDelaySystem Delay = default!;
+
+ [Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
+ [Dependency] private readonly SharedTransformSystem _xform = default!;
+
+ protected const string TeleportDelay = "TeleportDelay";
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnUiOpenAttempt);
+ SubscribeLocalEvent(OnTeleportToLocationRequest);
+ }
+
+ private void OnUiOpenAttempt(Entity ent, ref ActivatableUIOpenAttemptEvent args)
+ {
+ if (!Delay.IsDelayed(ent.Owner, TeleportDelay))
+ return;
+
+ args.Cancel();
+ }
+
+ protected virtual void OnTeleportToLocationRequest(Entity ent, ref TeleportLocationDestinationMessage args)
+ {
+ if (!TryGetEntity(args.NetEnt, out var telePointEnt) || TerminatingOrDeleted(telePointEnt) || !HasComp(telePointEnt) || Delay.IsDelayed(ent.Owner, TeleportDelay))
+ return;
+
+ var comp = ent.Comp;
+ var originEnt = args.Actor;
+ var telePointXForm = Transform(telePointEnt.Value);
+
+ SpawnAtPosition(comp.TeleportEffect, Transform(originEnt).Coordinates);
+
+ _xform.SetMapCoordinates(originEnt, _xform.GetMapCoordinates(telePointEnt.Value, telePointXForm));
+
+ SpawnAtPosition(comp.TeleportEffect, telePointXForm.Coordinates);
+
+ Delay.TryResetDelay(ent.Owner, true, id: TeleportDelay);
+
+ if (!ent.Comp.CloseAfterTeleport)
+ return;
+
+ // Teleport's done, now tell the BUI to close if needed.
+ _ui.CloseUi(ent.Owner, TeleportLocationUiKey.Key);
+ }
+}
diff --git a/Content.Shared/Teleportation/TeleportLocationsUi.cs b/Content.Shared/Teleportation/TeleportLocationsUi.cs
new file mode 100644
index 0000000000..f4ca97584a
--- /dev/null
+++ b/Content.Shared/Teleportation/TeleportLocationsUi.cs
@@ -0,0 +1,19 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Teleportation;
+
+[Serializable, NetSerializable]
+public enum TeleportLocationUiKey : byte
+{
+ Key
+}
+
+///
+/// Sends message to request that the clicker teleports to the requested location
+///
+[Serializable, NetSerializable]
+public sealed class TeleportLocationDestinationMessage(NetEntity netEnt, string pointName) : BoundUserInterfaceMessage
+{
+ public NetEntity NetEnt = netEnt;
+ public string PointName = pointName;
+}
diff --git a/Content.Shared/Warps/WarpPointComponent.cs b/Content.Shared/Warps/WarpPointComponent.cs
new file mode 100644
index 0000000000..61e84a660c
--- /dev/null
+++ b/Content.Shared/Warps/WarpPointComponent.cs
@@ -0,0 +1,27 @@
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Warps;
+
+///
+/// Allows ghosts etc to warp to this entity by name.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class WarpPointComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite), DataField]
+ public string? Location;
+
+ ///
+ /// If true, ghosts warping to this entity will begin following it.
+ ///
+ [DataField]
+ public bool Follow;
+
+ ///
+ /// What points should be excluded?
+ /// Useful where you want things like a ghost to reach only like CentComm
+ ///
+ [DataField]
+ public EntityWhitelist? Blacklist;
+}
diff --git a/Resources/Locale/en-US/teleportation/teleportation-menu-gui.ftl b/Resources/Locale/en-US/teleportation/teleportation-menu-gui.ftl
new file mode 100644
index 0000000000..847f2cbc54
--- /dev/null
+++ b/Resources/Locale/en-US/teleportation/teleportation-menu-gui.ftl
@@ -0,0 +1,6 @@
+## Default
+teleportation-menu-default-window-title = Teleportation Menu
+
+## Wizard
+teleportation-scroll-window-title = Teleportation Scroll
+teleportation-scroll-speech-wizard = EY TCHEL TORT TU {$location}
diff --git a/Resources/Maps/centcomm.yml b/Resources/Maps/centcomm.yml
index 39ed39ed9e..6405c65923 100644
--- a/Resources/Maps/centcomm.yml
+++ b/Resources/Maps/centcomm.yml
@@ -1,10 +1,10 @@
meta:
format: 7
category: Grid
- engineVersion: 247.2.0
+ engineVersion: 250.0.0
forkId: ""
forkVersion: ""
- time: 03/05/2025 09:01:26
+ time: 04/24/2025 00:06:42
entityCount: 9680
maps: []
grids:
@@ -21722,6 +21722,88 @@ entities:
- type: Transform
pos: 3.5,-12.5
parent: 1668
+- proto: ChemistryBottleEpinephrine
+ entities:
+ - uid: 6859
+ components:
+ - type: Transform
+ parent: 6846
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6860
+ components:
+ - type: Transform
+ parent: 6846
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6867
+ components:
+ - type: Transform
+ parent: 6865
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6871
+ components:
+ - type: Transform
+ parent: 6865
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+- proto: ChemistryBottleOmnizine
+ entities:
+ - uid: 6862
+ components:
+ - type: Transform
+ parent: 6846
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6863
+ components:
+ - type: Transform
+ parent: 6846
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6866
+ components:
+ - type: Transform
+ parent: 6865
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+ - uid: 6876
+ components:
+ - type: Transform
+ parent: 6865
+ - type: Physics
+ canCollide: False
+ - type: InsideEntityStorage
+- proto: ChemistryBottleUnstableMutagen
+ entities:
+ - uid: 1035
+ components:
+ - type: Transform
+ pos: 7.383148,-17.230762
+ parent: 1668
+ - uid: 1036
+ components:
+ - type: Transform
+ pos: 7.6053705,-17.223818
+ parent: 1668
+ - uid: 1037
+ components:
+ - type: Transform
+ pos: 7.5012035,-17.411318
+ parent: 1668
+ - uid: 1038
+ components:
+ - type: Transform
+ pos: 7.7303705,-17.411318
+ parent: 1668
- proto: ChemistryHotplate
entities:
- uid: 671
@@ -23874,36 +23956,34 @@ entities:
- type: Transform
pos: -12.5,5.5
parent: 1668
-- proto: DefaultStationBeacon
+- proto: DefaultStationBeaconCentComm
entities:
- uid: 4656
components:
- type: Transform
pos: -0.5,3.5
parent: 1668
- - type: NavMapBeacon
- text: CentComm
+- proto: DefaultStationBeaconCentCommAfterhours
+ entities:
- uid: 9452
components:
- type: Transform
pos: 22.5,-21.5
parent: 1668
- - type: NavMapBeacon
- text: Afterhours
- - uid: 9479
- components:
- - type: Transform
- pos: -0.5,-41.5
- parent: 1668
- - type: NavMapBeacon
- text: Thunderdome
+- proto: DefaultStationBeaconCentCommERT
+ entities:
- uid: 9480
components:
- type: Transform
pos: -41.5,-7.5
parent: 1668
- - type: NavMapBeacon
- text: ERT
+- proto: DefaultStationBeaconCentCommThunderdome
+ entities:
+ - uid: 9479
+ components:
+ - type: Transform
+ pos: -0.5,-41.5
+ parent: 1668
- proto: DefibrillatorCabinetFilled
entities:
- uid: 511
@@ -26409,36 +26489,6 @@ entities:
- type: Transform
pos: 13.91264,32.80469
parent: 1668
-- proto: EpinephrineChemistryBottle
- entities:
- - uid: 6859
- components:
- - type: Transform
- parent: 6846
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6860
- components:
- - type: Transform
- parent: 6846
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6867
- components:
- - type: Transform
- parent: 6865
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6871
- components:
- - type: Transform
- parent: 6865
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- proto: ERTEngineerPDA
entities:
- uid: 6784
@@ -43141,36 +43191,6 @@ entities:
- type: Transform
pos: -1.4979519,1.1034296
parent: 1668
-- proto: OmnizineChemistryBottle
- entities:
- - uid: 6862
- components:
- - type: Transform
- parent: 6846
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6863
- components:
- - type: Transform
- parent: 6846
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6866
- components:
- - type: Transform
- parent: 6865
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- - uid: 6876
- components:
- - type: Transform
- parent: 6865
- - type: Physics
- canCollide: False
- - type: InsideEntityStorage
- proto: OreProcessor
entities:
- uid: 4080
@@ -53982,28 +54002,6 @@ entities:
- Left: Reverse
- Right: Forward
- Middle: Off
-- proto: UnstableMutagenChemistryBottle
- entities:
- - uid: 1035
- components:
- - type: Transform
- pos: 7.383148,-17.230762
- parent: 1668
- - uid: 1036
- components:
- - type: Transform
- pos: 7.6053705,-17.223818
- parent: 1668
- - uid: 1037
- components:
- - type: Transform
- pos: 7.5012035,-17.411318
- parent: 1668
- - uid: 1038
- components:
- - type: Transform
- pos: 7.7303705,-17.411318
- parent: 1668
- proto: UraniumReinforcedWindowDirectional
entities:
- uid: 9601
diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml
index f334747024..a8fd6e2b2d 100644
--- a/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml
+++ b/Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml
@@ -270,6 +270,7 @@
- type: StorageFill
contents:
- id: OxygenTankFilled
- - id: ClothingOuterHardsuitWizard
- id: ClothingMaskBreath
- - id: JetpackVoidFilled
+ # TODO: Gone until reworked to have no space protection
+ #- id: ClothingOuterHardsuitWizard
+ #- id: JetpackVoidFilled
diff --git a/Resources/Prototypes/Entities/Markers/warp_point.yml b/Resources/Prototypes/Entities/Markers/warp_point.yml
index 2536fde474..675938c09b 100644
--- a/Resources/Prototypes/Entities/Markers/warp_point.yml
+++ b/Resources/Prototypes/Entities/Markers/warp_point.yml
@@ -16,6 +16,22 @@
- type: WarpPoint
location: beacon
+# Use for areas like CC
+- type: entity
+ id: GhostWarpPoint
+ parent: MarkerBase
+ name: ghost only warp point
+ components:
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
+ - type: WarpPoint
+ blacklist:
+ tags:
+ - GhostOnlyWarp
+ - type: Sprite
+ state: pink
+
- type: entity
parent: WarpPoint
id: WarpPointBombing
@@ -23,8 +39,14 @@
suffix: ninja bombing target
components:
- type: BombingTarget
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
location: bombing target
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Sprite
layers:
- state: pink
diff --git a/Resources/Prototypes/Entities/Mobs/Player/narsie.yml b/Resources/Prototypes/Entities/Mobs/Player/narsie.yml
index 5d07409b5f..f2b81f796c 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/narsie.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/narsie.yml
@@ -94,6 +94,12 @@
- type: GravityWell
baseRadialAcceleration: 6
maxRange: 8
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
location: Nar'Sie
+ blacklist:
+ tags:
+ - GhostOnlyWarp
diff --git a/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml b/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml
index 530f5e1037..658f14a6d4 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/ratvar.yml
@@ -89,6 +89,12 @@
- type: GravityWell
baseRadialAcceleration: 6
maxRange: 8
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
location: Ratvar
+ blacklist:
+ tags:
+ - GhostOnlyWarp
diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
index 934e9d3674..99a4cbd796 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
@@ -105,6 +105,9 @@
description: Handles AI interactions across holocards + AI cores
components:
- type: ItemSlots
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: StationAiHolder
slot:
name: station-ai-mind-slot
@@ -197,6 +200,9 @@
suffix: Empty
components:
- type: WarpPoint
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: ContainerComp
proto: AiHeld
container: station_ai_mind_slot
@@ -327,8 +333,14 @@
categories: [ HideSpawnMenu, DoNotMap ]
components:
- type: NoFTL
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Eye
pvsScale: 1.5
- type: Visibility
@@ -349,8 +361,14 @@
components:
- type: Transform
anchored: true
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Eye
- type: ContentEye
- type: Examiner
diff --git a/Resources/Prototypes/Entities/Objects/Devices/station_beacon.yml b/Resources/Prototypes/Entities/Objects/Devices/station_beacon.yml
index 3d5b78397e..569fd47d00 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/station_beacon.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/station_beacon.yml
@@ -713,3 +713,50 @@
components:
- type: NavMapBeacon
defaultText: station-beacon-vox
+
+# Ghost Only Beacons
+- type: entity
+ parent: DefaultStationBeacon
+ id: DefaultStationBeaconGhost
+ suffix: Boo
+ components:
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
+ - type: WarpPoint
+ blacklist:
+ tags:
+ - GhostOnlyWarp
+
+# CentComm Beacons
+- type: entity
+ parent: DefaultStationBeaconGhost
+ id: DefaultStationBeaconCentComm
+ suffix: CentComm
+ components:
+ - type: NavMapBeacon
+ text: CentComm
+
+- type: entity
+ parent: DefaultStationBeaconGhost
+ id: DefaultStationBeaconCentCommAfterhours
+ suffix: CentComm Afterhours
+ components:
+ - type: NavMapBeacon
+ text: Afterhours
+
+- type: entity
+ parent: DefaultStationBeaconGhost
+ id: DefaultStationBeaconCentCommThunderdome
+ suffix: CentComm Thunder Dome
+ components:
+ - type: NavMapBeacon
+ text: Thunderdome
+
+- type: entity
+ parent: DefaultStationBeaconGhost
+ id: DefaultStationBeaconCentCommERT
+ suffix: CentComm ERT
+ components:
+ - type: NavMapBeacon
+ text: ERT
diff --git a/Resources/Prototypes/Entities/Objects/Fun/immovable_rod.yml b/Resources/Prototypes/Entities/Objects/Fun/immovable_rod.yml
index bbadf4f220..324502c3d1 100644
--- a/Resources/Prototypes/Entities/Objects/Fun/immovable_rod.yml
+++ b/Resources/Prototypes/Entities/Objects/Fun/immovable_rod.yml
@@ -32,6 +32,9 @@
- type: WarpPoint
follow: true
location: immovable rod
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: entity
id: ImmovableRodDespawn
diff --git a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
index e1fc3fa5b6..523385788b 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
@@ -17,9 +17,13 @@
- type: WarpPoint
follow: true
location: nuke disk
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Tag
tags:
- HighRiskItem
+ - GhostOnlyWarp
- type: StealTarget
stealGroup: NukeDisk
diff --git a/Resources/Prototypes/Entities/Objects/Power/powersink.yml b/Resources/Prototypes/Entities/Objects/Power/powersink.yml
index 40406209a7..5d1043f08c 100644
--- a/Resources/Prototypes/Entities/Objects/Power/powersink.yml
+++ b/Resources/Prototypes/Entities/Objects/Power/powersink.yml
@@ -45,5 +45,11 @@
- type: Sprite
sprite: Objects/Power/powersink.rsi
state: powersink
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
location: powersink
+ blacklist:
+ tags:
+ - GhostOnlyWarp
diff --git a/Resources/Prototypes/Entities/Structures/Machines/nuke.yml b/Resources/Prototypes/Entities/Structures/Machines/nuke.yml
index 7fdd80bd2b..0ac4a9e98f 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/nuke.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/nuke.yml
@@ -107,9 +107,15 @@
Nuke: !type:ContainerSlot
- type: StealTarget
stealGroup: NuclearBomb
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
location: nuclear bomb
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: FTLSmashImmune
- type: entity
diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml
index 461b17efbb..1e439ddae4 100644
--- a/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml
+++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Singularity/singularity.yml
@@ -66,9 +66,15 @@
- SingularityEngine
- SingularityTeslaEngine
- Power
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
location: singularity
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Sprite
sprite: Structures/Power/Generation/Singularity/singularity_1.rsi
shader: unshaded
diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml
index 909601e066..d31f7526ab 100644
--- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml
+++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml
@@ -89,9 +89,15 @@
- type: ChaoticJump
jumpMinInterval: 8
jumpMaxInterval: 15
+ - type: Tag
+ tags:
+ - GhostOnlyWarp
- type: WarpPoint
follow: true
location: tesla ball
+ blacklist:
+ tags:
+ - GhostOnlyWarp
- type: Sprite
drawdepth: Effects
sprite: Structures/Power/Generation/Tesla/energy_ball.rsi
diff --git a/Resources/Prototypes/Magic/teleport_scroll.yml b/Resources/Prototypes/Magic/teleport_scroll.yml
new file mode 100644
index 0000000000..89c9ae5163
--- /dev/null
+++ b/Resources/Prototypes/Magic/teleport_scroll.yml
@@ -0,0 +1,26 @@
+- type: entity
+ id: WizardTeleportScroll
+ name: teleport scroll
+ suffix: Wizard
+ parent: [ BaseItem, BaseMagicalContraband ]
+ components:
+ - type: UserInterface
+ interfaces:
+ enum.TeleportLocationUiKey.Key:
+ type: TeleportLocationsBoundUserInterface
+ - type: ActivatableUI
+ key: enum.TeleportLocationUiKey.Key
+ - type: Sprite
+ sprite: Objects/Magic/magicactions.rsi
+ layers:
+ - state: spell_default
+ - type: TeleportLocations
+ name: teleportation-scroll-window-title
+ teleportEffect: WizardSmoke
+ closeAfterTeleport: true
+ speech: teleportation-scroll-speech-wizard
+ - type: UseDelay
+ delay: 1
+ delays:
+ TeleportDelay: !type:UseDelayInfo
+ length: 300
diff --git a/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml
index d296a02754..d137df195e 100644
--- a/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml
+++ b/Resources/Prototypes/Roles/Jobs/Fun/wizard_startinggear.yml
@@ -10,7 +10,7 @@
id: WizardPDA
ears: ClothingHeadsetAltWizard
belt: ClothingBeltWand
- # pocket1: TODO: Include wizard teleport scroll
+ pocket1: WizardTeleportScroll
pocket2: WizardsGrimoire
- type: startingGear
@@ -28,9 +28,3 @@
jumpsuit: ClothingUniformJumpsuitColorPurple
head: ClothingHeadHatVioletwizard
outerClothing: ClothingOuterWizardViolet
-
-- type: startingGear
- id: WizardHardsuitGear
- parent: WizardVioletGear
- equipment:
- outerClothing: ClothingOuterHardsuitWizard
diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml
index efd74cfe64..9020bec89f 100644
--- a/Resources/Prototypes/tags.yml
+++ b/Resources/Prototypes/tags.yml
@@ -581,6 +581,10 @@
- type: Tag
id: GeigerCounter
+# Used for warps
+- type: Tag
+ id: GhostOnlyWarp
+
- type: Tag
id: GlassAirlock