Add universal pinpointer (#13854)

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Chief-Engineer
2023-05-28 05:24:09 -05:00
committed by GitHub
parent 9384651a3f
commit 57cd8006f9
5 changed files with 140 additions and 15 deletions

View File

@@ -3,6 +3,7 @@ using Content.Shared.Pinpointer;
using System.Linq; using System.Linq;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Content.Server.Shuttles.Events; using Content.Server.Shuttles.Events;
using Content.Shared.IdentityManagement;
namespace Content.Server.Pinpointer; namespace Content.Server.Pinpointer;
@@ -18,12 +19,6 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget); SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget);
} }
private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args)
{
TogglePinpointer(uid, component);
LocateTarget(uid, component);
}
public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null) public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
{ {
if (!Resolve(uid, ref pinpointer)) if (!Resolve(uid, ref pinpointer))
@@ -43,6 +38,14 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
_appearance.SetData(uid, PinpointerVisuals.TargetDistance, pinpointer.DistanceToTarget, appearance); _appearance.SetData(uid, PinpointerVisuals.TargetDistance, pinpointer.DistanceToTarget, appearance);
} }
private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args)
{
TogglePinpointer(uid, component);
if (!component.CanRetarget)
LocateTarget(uid, component);
}
private void OnLocateTarget(ref FTLCompletedEvent ev) private void OnLocateTarget(ref FTLCompletedEvent ev)
{ {
// This feels kind of expensive, but it only happens once per hyperspace jump // This feels kind of expensive, but it only happens once per hyperspace jump
@@ -50,8 +53,12 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
// todo: ideally, you would need to raise this event only on jumped entities // todo: ideally, you would need to raise this event only on jumped entities
// this code update ALL pinpointers in game // this code update ALL pinpointers in game
var query = EntityQueryEnumerator<PinpointerComponent>(); var query = EntityQueryEnumerator<PinpointerComponent>();
while (query.MoveNext(out var uid, out var pinpointer)) while (query.MoveNext(out var uid, out var pinpointer))
{ {
if (pinpointer.CanRetarget)
continue;
LocateTarget(uid, pinpointer); LocateTarget(uid, pinpointer);
} }
} }
@@ -189,7 +196,7 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
return dir; return dir;
} }
private static Distance CalculateDistance(Vector2 vec, PinpointerComponent pinpointer) private Distance CalculateDistance(Vector2 vec, PinpointerComponent pinpointer)
{ {
var dist = vec.Length; var dist = vec.Length;
if (dist <= pinpointer.ReachedDistance) if (dist <= pinpointer.ReachedDistance)

View File

@@ -12,7 +12,7 @@ namespace Content.Shared.Pinpointer;
public sealed partial class PinpointerComponent : Component public sealed partial class PinpointerComponent : Component
{ {
// TODO: Type serializer oh god // TODO: Type serializer oh god
[DataField("component")] [DataField("component"), ViewVariables(VVAccess.ReadWrite)]
public string? Component; public string? Component;
[DataField("mediumDistance"), ViewVariables(VVAccess.ReadWrite)] [DataField("mediumDistance"), ViewVariables(VVAccess.ReadWrite)]
@@ -30,19 +30,34 @@ public sealed partial class PinpointerComponent : Component
[DataField("precision"), ViewVariables(VVAccess.ReadWrite)] [DataField("precision"), ViewVariables(VVAccess.ReadWrite)]
public double Precision = 0.09; public double Precision = 0.09;
/// <summary>
/// Name to display of the target being tracked.
/// </summary>
[DataField("targetName"), ViewVariables(VVAccess.ReadWrite)]
public string? TargetName;
/// <summary>
/// Whether or not the target name should be updated when the target is updated.
/// </summary>
[DataField("updateTargetName"), ViewVariables(VVAccess.ReadWrite)]
public bool UpdateTargetName;
/// <summary>
/// Whether or not the target can be reassigned.
/// </summary>
[DataField("canRetarget"), ViewVariables(VVAccess.ReadWrite)]
public bool CanRetarget;
[ViewVariables] [ViewVariables]
public EntityUid? Target = null; public EntityUid? Target = null;
[ViewVariables] [ViewVariables, AutoNetworkedField]
[AutoNetworkedField]
public bool IsActive = false; public bool IsActive = false;
[ViewVariables] [ViewVariables, AutoNetworkedField]
[AutoNetworkedField]
public Angle ArrowAngle; public Angle ArrowAngle;
[ViewVariables] [ViewVariables, AutoNetworkedField]
[AutoNetworkedField]
public Distance DistanceToTarget = Distance.Unknown; public Distance DistanceToTarget = Distance.Unknown;
[ViewVariables] [ViewVariables]

View File

@@ -1,7 +1,77 @@
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Emag.Systems;
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
namespace Content.Shared.Pinpointer; namespace Content.Shared.Pinpointer;
public abstract class SharedPinpointerSystem : EntitySystem public abstract class SharedPinpointerSystem : EntitySystem
{ {
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PinpointerComponent, GotEmaggedEvent>(OnEmagged);
SubscribeLocalEvent<PinpointerComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<PinpointerComponent, ExaminedEvent>(OnExamined);
}
/// <summary>
/// Set the target if capable
/// </summary>
private void OnAfterInteract(EntityUid uid, PinpointerComponent component, AfterInteractEvent args)
{
if (!args.CanReach || args.Target is not { } target)
return;
if (!component.CanRetarget || component.IsActive)
return;
// TODO add doafter once the freeze is lifted
args.Handled = true;
component.Target = args.Target;
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):player} set target of {ToPrettyString(uid):pinpointer} to {ToPrettyString(component.Target.Value):target}");
if (component.UpdateTargetName)
component.TargetName = component.Target == null ? null : Identity.Name(component.Target.Value, EntityManager);
}
/// <summary>
/// Set pinpointers target to track
/// </summary>
public void SetTarget(EntityUid uid, EntityUid? target, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return;
if (pinpointer.Target == target)
return;
pinpointer.Target = target;
if (pinpointer.UpdateTargetName)
pinpointer.TargetName = target == null ? null : Identity.Name(target.Value, EntityManager);
if (pinpointer.IsActive)
UpdateDirectionToTarget(uid, pinpointer);
}
/// <summary>
/// Update direction from pinpointer to selected target (if it was set)
/// </summary>
protected virtual void UpdateDirectionToTarget(EntityUid uid, PinpointerComponent? pinpointer = null)
{
}
private void OnExamined(EntityUid uid, PinpointerComponent component, ExaminedEvent args)
{
if (!args.IsInDetailsRange || component.TargetName == null)
return;
args.PushMarkup(Loc.GetString("examine-pinpointer-linked", ("target", component.TargetName)));
}
/// <summary> /// <summary>
/// Manually set distance from pinpointer to target /// Manually set distance from pinpointer to target
/// </summary> /// </summary>
@@ -49,4 +119,25 @@ public abstract class SharedPinpointerSystem : EntitySystem
pinpointer.IsActive = isActive; pinpointer.IsActive = isActive;
Dirty(pinpointer); Dirty(pinpointer);
} }
/// <summary>
/// Toggle Pinpointer screen. If it has target it will start tracking it.
/// </summary>
/// <returns>True if pinpointer was activated, false otherwise</returns>
public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return false;
var isActive = !pinpointer.IsActive;
SetActive(uid, isActive, pinpointer);
return isActive;
}
private void OnEmagged(EntityUid uid, PinpointerComponent component, ref GotEmaggedEvent args)
{
args.Handled = true;
component.CanRetarget = true;
}
} }

View File

@@ -0,0 +1 @@
examine-pinpointer-linked = It is tracking: {$target}

View File

@@ -1,6 +1,6 @@
- type: entity - type: entity
name: pinpointer name: pinpointer
description: A handheld tracking device that locks onto certain signals. description: A handheld tracking device. While typically far more capable, this one has been configured to lock onto certain signals.
parent: BaseItem parent: BaseItem
id: PinpointerBase id: PinpointerBase
abstract: true abstract: true
@@ -43,3 +43,14 @@
components: components:
- type: Pinpointer - type: Pinpointer
component: NukeDisk component: NukeDisk
targetName: nuclear authentication disk
- type: entity
name: universal pinpointer
description: A handheld tracking device that locks onto any physical entity while off.
id: PinpointerUniversal
parent: PinpointerBase
components:
- type: Pinpointer
updateTargetName: true
canRetarget: true