Portals & hand teleporter (#13266)
* basic system with portals & linked ents * hand tele sprites, no impl * hand tele and teleportation works * fancy it up * oog * special case projectiles * predict portal-to-portal teleportation * this stuff * check nullspace * sloth * give to rd instead * i guess this can probably happen * docs
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
using Content.Shared.Audio;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Teleportation.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Creates portals. If two are created, both are linked together--otherwise the first teleports randomly.
|
||||
/// Using it with both portals active deactivates both.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class HandTeleporterComponent : Component
|
||||
{
|
||||
[ViewVariables, DataField("firstPortal")]
|
||||
public EntityUid? FirstPortal = null;
|
||||
|
||||
[ViewVariables, DataField("secondPortal")]
|
||||
public EntityUid? SecondPortal = null;
|
||||
|
||||
[DataField("firstPortalPrototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string FirstPortalPrototype = "PortalRed";
|
||||
|
||||
[DataField("secondPortalPrototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string SecondPortalPrototype = "PortalBlue";
|
||||
|
||||
[DataField("newPortalSound")]
|
||||
public SoundSpecifier NewPortalSound = new SoundPathSpecifier("/Audio/Machines/high_tech_confirm.ogg")
|
||||
{
|
||||
Params = AudioParams.Default.WithVolume(-2f)
|
||||
};
|
||||
|
||||
[DataField("clearPortalsSound")]
|
||||
public SoundSpecifier ClearPortalsSound = new SoundPathSpecifier("/Audio/Machines/button.ogg");
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Content.Shared.Teleportation.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Teleportation.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entity which is linked to other entities (perhaps portals), and which can be walked through/
|
||||
/// thrown into to teleport an entity.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(LinkedEntitySystem)), NetworkedComponent]
|
||||
public sealed class LinkedEntityComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The entities that this entity is linked to.
|
||||
/// </summary>
|
||||
[DataField("linkedEntities")]
|
||||
public HashSet<EntityUid> LinkedEntities = new();
|
||||
|
||||
/// <summary>
|
||||
/// Should this entity be deleted if all of its links are removed?
|
||||
/// </summary>
|
||||
[DataField("deleteOnEmptyLinks")]
|
||||
public bool DeleteOnEmptyLinks = false;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class LinkedEntityComponentState : ComponentState
|
||||
{
|
||||
public HashSet<EntityUid> LinkedEntities;
|
||||
|
||||
public LinkedEntityComponentState(HashSet<EntityUid> linkedEntities)
|
||||
{
|
||||
LinkedEntities = linkedEntities;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum LinkedEntityVisuals : byte
|
||||
{
|
||||
HasAnyLinks
|
||||
}
|
||||
31
Content.Shared/Teleportation/Components/PortalComponent.cs
Normal file
31
Content.Shared/Teleportation/Components/PortalComponent.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Teleportation.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Marks an entity as being a 'portal' which teleports entities sent through it to linked entities.
|
||||
/// Relies on <see cref="LinkedEntityComponent"/> being set up.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class PortalComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Sound played on arriving to this portal, centered on the destination.
|
||||
/// The arrival sound of the entered portal will play if the destination is not a portal.
|
||||
/// </summary>
|
||||
[DataField("arrivalSound")]
|
||||
public SoundSpecifier ArrivalSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Sound played on departing from this portal, centered on the original portal.
|
||||
/// </summary>
|
||||
[DataField("departureSound")]
|
||||
public SoundSpecifier DepartureSound = new SoundPathSpecifier("/Audio/Effects/teleport_departure.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// If no portals are linked, the subject will be teleported a random distance at maximum this far away.
|
||||
/// </summary>
|
||||
[DataField("maxRandomRadius")]
|
||||
public float MaxRandomRadius = 10.0f;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Teleportation.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Attached to an entity after portal transit to mark that they should not immediately be portaled back
|
||||
/// at the end destination.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class PortalTimeoutComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The portal that was entered. Null if coming from a hand teleporter, etc.
|
||||
/// </summary>
|
||||
[ViewVariables, DataField("enteredPortal")]
|
||||
public EntityUid? EnteredPortal = null;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PortalTimeoutComponentState : ComponentState
|
||||
{
|
||||
public EntityUid? EnteredPortal;
|
||||
|
||||
public PortalTimeoutComponentState(EntityUid? enteredPortal)
|
||||
{
|
||||
EnteredPortal = enteredPortal;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user