Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navmap Warp #31653

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
48 changes: 28 additions & 20 deletions Content.Client/Pinpointer/UI/NavMapControl.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Input;
Expand All @@ -18,6 +19,7 @@
using JetBrains.Annotations;
using Content.Shared.Atmos;
using System.Linq;
using Robust.Shared.Player;
using Robust.Shared.Utility;

namespace Content.Client.Pinpointer.UI;
Expand All @@ -29,6 +31,7 @@ namespace Content.Client.Pinpointer.UI;
public partial class NavMapControl : MapGridControl
{
[Dependency] private IResourceCache _cache = default!;
[Dependency] private readonly ISharedPlayerManager? _player = default;
private readonly SharedTransformSystem _transformSystem;
private readonly SharedNavMapSystem _navMapSystem;

Expand Down Expand Up @@ -202,24 +205,9 @@ protected override void KeyBindUp(GUIBoundKeyEventArgs args)

if (args.Function == EngineKeyFunctions.UIClick)
{
if (TrackedEntitySelectedAction == null)
if (TrackedEntitySelectedAction == null || !CalculateWorldPos(args, out var worldPosition))
return;

if (_xform == null || _physics == null || TrackedEntities.Count == 0)
return;

// If the cursor has moved a significant distance, exit
if ((StartDragPosition - args.PointerLocation.Position).Length() > MinDragDistance)
return;

// Get the clicked position
var offset = Offset + _physics.LocalCenter;
var localPosition = args.PointerLocation.Position - GlobalPixelPosition;

// Convert to a world position
var unscaledPosition = (localPosition - MidPointVector) / MinimapScale;
var worldPosition = Vector2.Transform(new Vector2(unscaledPosition.X, -unscaledPosition.Y) + offset, _transformSystem.GetWorldMatrix(_xform));

// Find closest tracked entity in range
var closestEntity = NetEntity.Invalid;
var closestDistance = float.PositiveInfinity;
Expand All @@ -228,8 +216,8 @@ protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
if (!blip.Selectable)
continue;
var currentDistance = (_transformSystem.ToMapCoordinates(blip.Coordinates).Position - worldPosition).Length();

var currentDistance = (_transformSystem.ToMapCoordinates(blip.Coordinates).Position - worldPosition.Value).Length();

if (closestDistance < currentDistance || currentDistance * MinimapScale > MaxSelectableDistance)
continue;
Expand All @@ -243,18 +231,38 @@ protected override void KeyBindUp(GUIBoundKeyEventArgs args)

TrackedEntitySelectedAction.Invoke(closestEntity);
}

else if (args.Function == EngineKeyFunctions.UIRightClick)
{
// Clear current selection with right click
TrackedEntitySelectedAction?.Invoke(null);
}

else if (args.Function == ContentKeyFunctions.ExamineEntity)
{
// Toggle beacon labels
_beacons.Pressed = !_beacons.Pressed;
}
else if (args.Function == ContentKeyFunctions.AltActivateItemInWorld)
{
if (_player?.LocalEntity is not null && CalculateWorldPos(args, out var pos))
_navMapSystem.RequestWarpTo(_player.LocalEntity.Value, pos.Value);
}
}

private bool CalculateWorldPos(GUIBoundKeyEventArgs args, [NotNullWhen(true)] out Vector2? worldPosition)
{
worldPosition = null;

if (_xform == null || _physics == null)
return false;

// Get the clicked position
var offset = Offset + _physics.LocalCenter;
var localPosition = args.PointerLocation.Position - GlobalPixelPosition;
// Convert to a world position
var unscaledPosition = (localPosition - MidPointVector) / MinimapScale;
worldPosition = Vector2.Transform(new Vector2(unscaledPosition.X, -unscaledPosition.Y) + offset, _transformSystem.GetWorldMatrix(_xform));

return true;
}

protected override void MouseMove(GUIMouseMoveEventArgs args)
Expand Down
26 changes: 26 additions & 0 deletions Content.Shared/Maps/NavMapWarpComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace Content.Shared.Maps;

/// <summary>
/// This enables an entity to teleport with any navMap by pressing a key over the map screen
/// </summary>
[RegisterComponent]
public sealed partial class NavMapWarpComponent : Component
{
Errant-4 marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>
/// A random sound from this list plays on the client of the warping mob
/// </summary>
[DataField]
public List<string> Sounds = new List<string>
{
"/Audio/Effects/static1.ogg",
"/Audio/Effects/static2.ogg",
"/Audio/Effects/static3.ogg"
};

Errant-4 marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>
/// Random pitch variance. Set to 0 for no randomness;
/// </summary>
[DataField]
public float PitchVariation = 0.1f;

}
17 changes: 17 additions & 0 deletions Content.Shared/Pinpointer/MapWarpRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Numerics;
using Robust.Shared.Serialization;

namespace Content.Shared.Pinpointer;

[Serializable, NetSerializable]
public sealed class MapWarpRequest: EntityEventArgs
Errant-4 marked this conversation as resolved.
Show resolved Hide resolved
{
public readonly NetEntity Uid;
public readonly Vector2 Target;

public MapWarpRequest(NetEntity uid, Vector2 target)
{
Target = target;
Uid = uid;
}
}
45 changes: 43 additions & 2 deletions Content.Shared/Pinpointer/SharedNavMapSystem.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
using Content.Shared.Maps;
using Content.Shared.Tag;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

namespace Content.Shared.Pinpointer;

Expand All @@ -23,7 +26,10 @@ public abstract class SharedNavMapSystem : EntitySystem
public const int WallMask = AllDirMask << (int) NavMapChunkType.Wall;
public const int FloorMask = AllDirMask << (int) NavMapChunkType.Floor;

[Robust.Shared.IoC.Dependency] private readonly SharedAudioSystem _audio = default!;
[Robust.Shared.IoC.Dependency] private readonly IRobustRandom _random = default!;
[Robust.Shared.IoC.Dependency] private readonly TagSystem _tagSystem = default!;
[Robust.Shared.IoC.Dependency] private readonly SharedTransformSystem _transformSystem = default!;

private static readonly ProtoId<TagPrototype>[] WallTags = {"Wall", "Window"};
private EntityQuery<NavMapDoorComponent> _doorQuery;
Expand All @@ -34,6 +40,9 @@ public override void Initialize()

// Data handling events
SubscribeLocalEvent<NavMapComponent, ComponentGetState>(OnGetState);

SubscribeNetworkEvent<MapWarpRequest>(OnMapWarp);

Errant-4 marked this conversation as resolved.
Show resolved Hide resolved
_doorQuery = GetEntityQuery<NavMapDoorComponent>();
}

Expand Down Expand Up @@ -81,6 +90,38 @@ protected bool TryCreateNavMapBeaconData(EntityUid uid, NavMapBeaconComponent co
return true;
}

public void RequestWarpTo(EntityUid uid, Vector2 target)
{
var message = new MapWarpRequest(GetNetEntity(uid), target);
RaiseNetworkEvent(message);
}

private void OnMapWarp(MapWarpRequest args)
{
var uid = GetEntity(args.Uid);

// This was only tested with the AI Eye but should theoretically work with any other future remote-controlled things
if (TryComp<EyeComponent>(uid, out var eye) && eye.Target is not null)
uid = eye.Target.Value;

if (!TryComp<NavMapWarpComponent>(uid, out var warpComp))
return;

var xform = Transform(uid);

if (xform.MapUid is null)
return;

var index = _random.Next(warpComp.Sounds.Count);
_audio.PlayGlobal(warpComp.Sounds[index],
GetEntity(args.Uid),
AudioParams.Default.WithVariation(warpComp.PitchVariation));

// This was designed for incorporeal entities, thus there aren't any collision checks or anything
_transformSystem.SetCoordinates(uid, xform, new EntityCoordinates(xform.MapUid.Value, args.Target));
_transformSystem.AttachToGridOrMap(uid, xform);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're better off just making it a BUI event so it gets validation done.

Also the audio should be predicted instead. Also don't do multiple transformsystem calls as it will double the amount of moveevents that get raised which are extremely expensive, just set the position once. Use PlaceAt or the likes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Audio is now predicted. I have removed the AttachToGridOrMap call entirely, because it does not actually seem to bee needed at all (it was mostly just skipped by checks anyway).

There is now also a 2 second "cooldown" on warps so they can't be spammed

#region: Event handling

private void OnGetState(EntityUid uid, NavMapComponent component, ref ComponentGetState args)
Expand Down
5 changes: 5 additions & 0 deletions Resources/Audio/Effects/attributions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,8 @@
copyright: '"beep_landmine.ogg" by kaktuscsc of Discord for SS14'
license: "CC-BY-SA-3.0"
source: https://github.com/YuriyKiss/space-station-14/commit/971a135a9c83aed46e967aac9302ab5b35562b5f

- files: [static1.ogg, static2.ogg, static3.ogg]
copyright: Errant (github username Errant-4)
license: CC-BY-SA-3.0
source: https://github.com/space-wizards/space-station-14/pull/31653
Binary file added Resources/Audio/Effects/static1.ogg
Binary file not shown.
Binary file added Resources/Audio/Effects/static2.ogg
Binary file not shown.
Binary file added Resources/Audio/Effects/static3.ogg
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
- type: Loadout
prototypes: [ MobAghostGear ]
- type: BypassInteractionChecks
- type: NavMapWarp

- type: entity
id: ActionAGhostShowSolar
Expand Down
1 change: 1 addition & 0 deletions Resources/Prototypes/Entities/Mobs/Player/silicon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@
- state: ai_camera
shader: unshaded
map: ["base"]
- type: NavMapWarp

# Borgs
- type: entity
Expand Down
Loading