Port the Mass Scanner from OR14 (#6172)

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
mirrorcult
2022-01-30 22:38:11 -07:00
committed by GitHub
parent 70e5dd9cc0
commit a055ec3514
9 changed files with 278 additions and 0 deletions

View File

@@ -283,6 +283,7 @@ namespace Content.Client.Entry
"AtmosAlarmable",
"FireAlarm",
"AirAlarm",
"RadarConsole",
"Guardian",
"GuardianCreator",
"GuardianHost",

View File

@@ -0,0 +1,8 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:radar="clr-namespace:Content.Client.Radar"
Title="{Loc 'radar-window-title'}"
Resizable="False">
<BoxContainer Orientation="Horizontal">
<radar:RadarControl Name="Radar"/>
</BoxContainer>
</DefaultWindow>

View File

@@ -0,0 +1,113 @@
using System;
using Content.Client.Computer;
using Content.Shared.Radar;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Maths;
namespace Content.Client.Radar;
[GenerateTypedNameReferences]
public partial class RadarConsoleWindow : DefaultWindow, IComputerWindow<RadarConsoleBoundInterfaceState>
{
public RadarConsoleWindow()
{
RobustXamlLoader.Load(this);
}
public void SetupComputerWindow(ComputerBoundUserInterfaceBase cb)
{
}
public void UpdateState(RadarConsoleBoundInterfaceState scc)
{
Radar.UpdateState(scc);
}
}
public sealed class RadarControl : Control
{
private float _radarArea = 256f;
private float RadarCircleRadius => MathF.Max(0, _radarArea - 8) / 2;
private RadarConsoleBoundInterfaceState _lastState = new(256f, Array.Empty<RadarObjectData>());
private float SizeFull => (int) (_radarArea * UIScale);
public int RadiusCircle => (int) (RadarCircleRadius * UIScale);
public RadarControl()
{
MinSize = (SizeFull, SizeFull);
}
public void UpdateState(RadarConsoleBoundInterfaceState ls)
{
if (!_radarArea.Equals(ls.Range * 2))
{
_radarArea = ls.Range * 2;
MinSize = (SizeFull, SizeFull);
}
_lastState = ls;
}
protected override void Draw(DrawingHandleScreen handle)
{
var point = SizeFull / 2;
var fakeAA = new Color(0.08f, 0.08f, 0.08f);
var gridLines = new Color(0.08f, 0.08f, 0.08f);
var gridLinesRadial = 8;
var gridLinesEquatorial = 8;
handle.DrawCircle((point, point), RadiusCircle + 1, fakeAA);
handle.DrawCircle((point, point), RadiusCircle, Color.Black);
for (var i = 0; i < gridLinesEquatorial; i++)
{
handle.DrawCircle((point, point), (RadiusCircle / gridLinesEquatorial) * i, gridLines, false);
}
for (var i = 0; i < gridLinesRadial; i++)
{
Angle angle = (Math.PI / gridLinesRadial) * i;
var aExtent = angle.ToVec() * RadiusCircle;
handle.DrawLine((point, point) - aExtent, (point, point) + aExtent, gridLines);
}
handle.DrawLine((point, point) + new Vector2(8, 8), (point, point) - new Vector2(0, 8), Color.Yellow);
handle.DrawLine((point, point) + new Vector2(-8, 8), (point, point) - new Vector2(0, 8), Color.Yellow);
foreach (var obj in _lastState.Objects)
{
if (obj.Position.Length > RadiusCircle - 24)
continue;
switch (obj.Shape)
{
case RadarObjectShape.CircleFilled:
case RadarObjectShape.Circle:
{
handle.DrawCircle(obj.Position + point, obj.Radius, obj.Color, obj.Shape == RadarObjectShape.CircleFilled);
break;
}
default:
throw new NotImplementedException();
}
}
}
}
[UsedImplicitly]
public class RadarConsoleBoundUserInterface : ComputerBoundUserInterface<RadarConsoleWindow, RadarConsoleBoundInterfaceState>
{
public RadarConsoleBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) {}
}

View File

@@ -0,0 +1,13 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Content.Server.Radar;
[RegisterComponent, ComponentProtoName("RadarConsole")]
public class RadarConsoleComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("range")]
public float Range = 256f;
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using Content.Server.Solar.Components;
using Content.Server.UserInterface;
using Content.Shared.Radar;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.Server.Radar;
public class RadarConsoleSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
private static float Frequency = 1.5f;
private float _accumulator;
public override void Update(float frameTime)
{
_accumulator += frameTime;
if (_accumulator < Frequency)
return;
_accumulator -= Frequency;
foreach (var (component, xform) in EntityManager.EntityQuery<RadarConsoleComponent, TransformComponent>())
{
var s = component.Owner.GetUIOrNull(RadarConsoleUiKey.Key);
if (s is null)
continue;
var (radarPos, _, radarInvMatrix) = xform.GetWorldPositionRotationInvMatrix();
var mapId = xform.MapID;
var objects = new List<RadarObjectData>();
_mapManager.FindGridsIntersectingEnumerator(mapId, new Box2(radarPos - component.Range, radarPos + component.Range), out var enumerator, true);
while (enumerator.MoveNext(out var grid))
{
var phy = Comp<PhysicsComponent>(grid.GridEntityId);
var transform = Transform(grid.GridEntityId);
if (phy.Mass < 50)
continue;
var rad = Math.Log2(phy.Mass);
var gridCenter = transform.WorldMatrix.Transform(phy.LocalCenter);
var pos = radarInvMatrix.Transform(gridCenter);
pos.Y = -pos.Y; // Robust has an inverted Y, like BYOND. This undoes that.
if (pos.Length > component.Range)
continue;
objects.Add(new RadarObjectData {Color = Color.Aqua, Position = pos, Radius = (float)rad});
}
s.SetState(new RadarConsoleBoundInterfaceState(component.Range, objects.ToArray()));
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
namespace Content.Shared.Radar;
[Serializable, NetSerializable]
public sealed class RadarConsoleBoundInterfaceState : BoundUserInterfaceState
{
public float Range;
public RadarObjectData[] Objects;
public RadarConsoleBoundInterfaceState(float range, RadarObjectData[] objects)
{
Range = range;
Objects = objects;
}
}
[Serializable, NetSerializable]
public struct RadarObjectData
{
public Color Color;
public RadarObjectShape Shape;
public Vector2 Position;
public float Radius;
}
public enum RadarObjectShape : byte
{
Circle,
CircleFilled,
}
[Serializable, NetSerializable]
public enum RadarConsoleUiKey : byte
{
Key
}

View File

@@ -0,0 +1 @@
radar-window-title = Mass Scanner Console

View File

@@ -67,6 +67,14 @@
- type: ComputerBoard
prototype: ComputerComms
- type: entity
parent: BaseComputerCircuitboard
id: RadarConsoleCircuitboard
name: radar console computer board
components:
- type: ComputerBoard
prototype: ComputerRadar
- type: entity
parent: BaseComputerCircuitboard
id: SolarControlComputerCircuitboard

View File

@@ -272,6 +272,32 @@
energy: 1.6
color: "#e6e227"
- type: entity
parent: ComputerBase
id: ComputerRadar
name: mass scanner computer
description: A computer for detecting nearby bodies, displaying them by position and mass.
components:
- type: Appearance
visuals:
- type: ComputerVisualizer
key: generic_key
screen: solar_screen
- type: RadarConsole
- type: ActivatableUI
key: enum.RadarConsoleUiKey.Key
- type: ActivatableUIRequiresPower
- type: UserInterface
interfaces:
- key: enum.RadarConsoleUiKey.Key
type: RadarConsoleBoundUserInterface
- type: Computer
board: RadarConsoleCircuitboard
- type: PointLight
radius: 1.5
energy: 1.6
color: "#e6e227"
- type: entity
id: ComputerSupplyOrdering
parent: ComputerBase