-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #89 from Space-Stories/master
Upstream branch sync
- Loading branch information
Showing
427 changed files
with
717,895 additions
and
572,196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
using System.Numerics; | ||
using Content.Shared.Mining.Components; | ||
using Robust.Client.GameObjects; | ||
using Robust.Client.Graphics; | ||
using Robust.Client.Player; | ||
using Robust.Shared.Enums; | ||
using Robust.Shared.Timing; | ||
using Robust.Shared.Utility; | ||
|
||
namespace Content.Client.Mining; | ||
|
||
public sealed class MiningOverlay : Overlay | ||
{ | ||
[Dependency] private readonly IEntityManager _entityManager = default!; | ||
[Dependency] private readonly IGameTiming _timing = default!; | ||
[Dependency] private readonly IPlayerManager _player = default!; | ||
private readonly EntityLookupSystem _lookup; | ||
private readonly SpriteSystem _sprite; | ||
private readonly TransformSystem _xform; | ||
|
||
private readonly EntityQuery<SpriteComponent> _spriteQuery; | ||
private readonly EntityQuery<TransformComponent> _xformQuery; | ||
|
||
public override OverlaySpace Space => OverlaySpace.WorldSpace; | ||
public override bool RequestScreenTexture => false; | ||
|
||
private readonly HashSet<Entity<MiningScannerViewableComponent>> _viewableEnts = new(); | ||
|
||
public MiningOverlay() | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
|
||
_lookup = _entityManager.System<EntityLookupSystem>(); | ||
_sprite = _entityManager.System<SpriteSystem>(); | ||
_xform = _entityManager.System<TransformSystem>(); | ||
|
||
_spriteQuery = _entityManager.GetEntityQuery<SpriteComponent>(); | ||
_xformQuery = _entityManager.GetEntityQuery<TransformComponent>(); | ||
} | ||
|
||
protected override void Draw(in OverlayDrawArgs args) | ||
{ | ||
var handle = args.WorldHandle; | ||
|
||
if (_player.LocalEntity is not { } localEntity || | ||
!_entityManager.TryGetComponent<MiningScannerViewerComponent>(localEntity, out var viewerComp)) | ||
return; | ||
|
||
if (viewerComp.LastPingLocation == null) | ||
return; | ||
|
||
var scaleMatrix = Matrix3Helpers.CreateScale(Vector2.One); | ||
|
||
_viewableEnts.Clear(); | ||
_lookup.GetEntitiesInRange(viewerComp.LastPingLocation.Value, viewerComp.ViewRange, _viewableEnts); | ||
foreach (var ore in _viewableEnts) | ||
{ | ||
if (!_xformQuery.TryComp(ore, out var xform) || | ||
!_spriteQuery.TryComp(ore, out var sprite)) | ||
continue; | ||
|
||
if (xform.MapID != args.MapId || !sprite.Visible) | ||
continue; | ||
|
||
if (!sprite.LayerMapTryGet(MiningScannerVisualLayers.Overlay, out var idx)) | ||
continue; | ||
var layer = sprite[idx]; | ||
|
||
if (layer.ActualRsi?.Path == null || layer.RsiState.Name == null) | ||
continue; | ||
|
||
var gridRot = xform.GridUid == null ? 0 : _xformQuery.CompOrNull(xform.GridUid.Value)?.LocalRotation ?? 0; | ||
var rotationMatrix = Matrix3Helpers.CreateRotation(gridRot); | ||
|
||
var worldMatrix = Matrix3Helpers.CreateTranslation(_xform.GetWorldPosition(xform)); | ||
var scaledWorld = Matrix3x2.Multiply(scaleMatrix, worldMatrix); | ||
var matty = Matrix3x2.Multiply(rotationMatrix, scaledWorld); | ||
handle.SetTransform(matty); | ||
|
||
var spriteSpec = new SpriteSpecifier.Rsi(layer.ActualRsi.Path, layer.RsiState.Name); | ||
var texture = _sprite.GetFrame(spriteSpec, TimeSpan.FromSeconds(layer.AnimationTime)); | ||
|
||
var animTime = (viewerComp.NextPingTime - _timing.CurTime).TotalSeconds; | ||
|
||
|
||
var alpha = animTime < viewerComp.AnimationDuration | ||
? 0 | ||
: (float) Math.Clamp((animTime - viewerComp.AnimationDuration) / viewerComp.AnimationDuration, 0f, 1f); | ||
var color = Color.White.WithAlpha(alpha); | ||
|
||
handle.DrawTexture(texture, -(Vector2) texture.Size / 2f / EyeManager.PixelsPerMeter, layer.Rotation, modulate: color); | ||
|
||
} | ||
handle.SetTransform(Matrix3x2.Identity); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using Content.Shared.Mining.Components; | ||
using Robust.Client.Graphics; | ||
using Robust.Client.Player; | ||
using Robust.Shared.Player; | ||
|
||
namespace Content.Client.Mining; | ||
|
||
/// <summary> | ||
/// This handles the lifetime of the <see cref="MiningOverlay"/> for a given entity. | ||
/// </summary> | ||
public sealed class MiningOverlaySystem : EntitySystem | ||
{ | ||
[Dependency] private readonly IPlayerManager _player = default!; | ||
[Dependency] private readonly IOverlayManager _overlayMan = default!; | ||
|
||
private MiningOverlay _overlay = default!; | ||
|
||
/// <inheritdoc/> | ||
public override void Initialize() | ||
{ | ||
SubscribeLocalEvent<MiningScannerViewerComponent, ComponentInit>(OnInit); | ||
SubscribeLocalEvent<MiningScannerViewerComponent, ComponentShutdown>(OnShutdown); | ||
SubscribeLocalEvent<MiningScannerViewerComponent, LocalPlayerAttachedEvent>(OnPlayerAttached); | ||
SubscribeLocalEvent<MiningScannerViewerComponent, LocalPlayerDetachedEvent>(OnPlayerDetached); | ||
|
||
_overlay = new(); | ||
} | ||
|
||
private void OnPlayerAttached(Entity<MiningScannerViewerComponent> ent, ref LocalPlayerAttachedEvent args) | ||
{ | ||
_overlayMan.AddOverlay(_overlay); | ||
} | ||
|
||
private void OnPlayerDetached(Entity<MiningScannerViewerComponent> ent, ref LocalPlayerDetachedEvent args) | ||
{ | ||
_overlayMan.RemoveOverlay(_overlay); | ||
} | ||
|
||
private void OnInit(Entity<MiningScannerViewerComponent> ent, ref ComponentInit args) | ||
{ | ||
if (_player.LocalEntity == ent) | ||
{ | ||
_overlayMan.AddOverlay(_overlay); | ||
} | ||
} | ||
|
||
private void OnShutdown(Entity<MiningScannerViewerComponent> ent, ref ComponentShutdown args) | ||
{ | ||
if (_player.LocalEntity == ent) | ||
{ | ||
_overlayMan.RemoveOverlay(_overlay); | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using Content.Server.Anomaly.Effects; | ||
using Content.Shared.Destructible.Thresholds; | ||
using Content.Shared.DeviceLinking; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server.Anomaly.Components; | ||
|
||
[RegisterComponent, AutoGenerateComponentPause, Access(typeof(TechAnomalySystem))] | ||
public sealed partial class TechAnomalyComponent : Component | ||
{ | ||
/// <summary> | ||
/// the distance at which random ports will bind to the anomaly. Scales with severity. | ||
/// </summary> | ||
[DataField] | ||
public MinMax LinkRadius = new(5, 10); | ||
|
||
/// <summary> | ||
/// the maximum number of entities with which an anomaly is associated during pulsing. Scales with severity | ||
/// </summary> | ||
[DataField] | ||
public MinMax LinkCountPerPulse = new(2, 8); | ||
|
||
/// <summary> | ||
/// Number of linkable pairs. when supercrit, the anomaly will link random devices in the radius to each other in pairs. | ||
/// </summary> | ||
[DataField] | ||
public int LinkCountSupercritical = 30; | ||
|
||
/// <summary> | ||
/// port activated by pulsation of the anomaly | ||
/// </summary> | ||
[DataField] | ||
public ProtoId<SourcePortPrototype> PulsePort = "Pulse"; | ||
|
||
/// <summary> | ||
/// A port that activates every few seconds of an anomaly's lifetime | ||
/// </summary> | ||
[DataField] | ||
public ProtoId<SourcePortPrototype> TimerPort = "Timer"; | ||
|
||
/// <summary> | ||
/// Chance of emag the device, when supercrit | ||
/// </summary> | ||
[DataField] | ||
public float EmagSupercritProbability = 0.4f; | ||
|
||
/// <summary> | ||
/// A prototype beam shot into devices when pulsed | ||
/// </summary> | ||
[DataField] | ||
public EntProtoId LinkBeamProto = "AnomalyTechBeam"; | ||
|
||
/// <summary> | ||
/// time until the next activation of the timer ports | ||
/// </summary> | ||
[DataField, AutoPausedField] | ||
public TimeSpan NextTimer = TimeSpan.Zero; | ||
|
||
[DataField] | ||
public float TimerFrequency = 3f; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
using Content.Server.Anomaly.Components; | ||
using Content.Server.Beam; | ||
using Content.Server.DeviceLinking.Systems; | ||
using Content.Shared.Anomaly.Components; | ||
using Content.Shared.DeviceLinking; | ||
using Content.Shared.Emag.Systems; | ||
using Robust.Shared.Random; | ||
using Robust.Shared.Timing; | ||
|
||
namespace Content.Server.Anomaly.Effects; | ||
|
||
public sealed class TechAnomalySystem : EntitySystem | ||
{ | ||
[Dependency] private readonly DeviceLinkSystem _signal = default!; | ||
[Dependency] private readonly EntityLookupSystem _lookup = default!; | ||
[Dependency] private readonly IRobustRandom _random = default!; | ||
[Dependency] private readonly BeamSystem _beam = default!; | ||
[Dependency] private readonly IGameTiming _timing = default!; | ||
[Dependency] private readonly EmagSystem _emag = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<TechAnomalyComponent, AnomalyPulseEvent>(OnPulse); | ||
SubscribeLocalEvent<TechAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical); | ||
SubscribeLocalEvent<TechAnomalyComponent, AnomalyStabilityChangedEvent>(OnStabilityChanged); | ||
} | ||
|
||
public override void Update(float frameTime) | ||
{ | ||
base.Update(frameTime); | ||
|
||
var query = EntityQueryEnumerator<TechAnomalyComponent, AnomalyComponent>(); | ||
while (query.MoveNext(out var uid, out var tech, out var anom)) | ||
{ | ||
if (_timing.CurTime < tech.NextTimer) | ||
return; | ||
|
||
tech.NextTimer = _timing.CurTime + TimeSpan.FromSeconds(tech.TimerFrequency * anom.Stability); | ||
|
||
_signal.InvokePort(uid, tech.TimerPort); | ||
} | ||
} | ||
|
||
private void OnStabilityChanged(Entity<TechAnomalyComponent> tech, ref AnomalyStabilityChangedEvent args) | ||
{ | ||
var links = MathHelper.Lerp(tech.Comp.LinkCountPerPulse.Min, tech.Comp.LinkCountPerPulse.Max, args.Severity); | ||
CreateNewRandomLink(tech, (int)links); | ||
} | ||
|
||
private void CreateNewRandomLink(Entity<TechAnomalyComponent> tech, int count) | ||
{ | ||
if (!TryComp<AnomalyComponent>(tech, out var anomaly)) | ||
return; | ||
if (!TryComp<DeviceLinkSourceComponent>(tech, out var sourceComp)) | ||
return; | ||
|
||
var range = MathHelper.Lerp(tech.Comp.LinkRadius.Min, tech.Comp.LinkRadius.Max, anomaly.Severity); | ||
|
||
var devices = _lookup.GetEntitiesInRange<DeviceLinkSinkComponent>(Transform(tech).Coordinates, range); | ||
if (devices.Count < 1) | ||
return; | ||
|
||
for (var i = 0; i < count; i++) | ||
{ | ||
var device = _random.Pick(devices); | ||
CreateNewLink(tech, (tech, sourceComp), device); | ||
} | ||
} | ||
|
||
private void CreateNewLink(Entity<TechAnomalyComponent> tech, Entity<DeviceLinkSourceComponent> source, Entity<DeviceLinkSinkComponent> target) | ||
{ | ||
var sourcePort = _random.Pick(source.Comp.Ports); | ||
var sinkPort = _random.Pick(target.Comp.Ports); | ||
|
||
_signal.SaveLinks(null, source, target,new() | ||
{ | ||
(sourcePort, sinkPort), | ||
}); | ||
_beam.TryCreateBeam(source, target, tech.Comp.LinkBeamProto); | ||
} | ||
|
||
private void OnSupercritical(Entity<TechAnomalyComponent> tech, ref AnomalySupercriticalEvent args) | ||
{ | ||
// We remove the component so that the anomaly does not bind itself to other devices before self destroy. | ||
RemComp<DeviceLinkSourceComponent>(tech); | ||
|
||
var sources = | ||
_lookup.GetEntitiesInRange<DeviceLinkSourceComponent>(Transform(tech).Coordinates, | ||
tech.Comp.LinkRadius.Max); | ||
|
||
var sinks = | ||
_lookup.GetEntitiesInRange<DeviceLinkSinkComponent>(Transform(tech).Coordinates, | ||
tech.Comp.LinkRadius.Max); | ||
|
||
for (var i = 0; i < tech.Comp.LinkCountSupercritical; i++) | ||
{ | ||
if (sources.Count < 1) | ||
return; | ||
|
||
if (sinks.Count < 1) | ||
return; | ||
|
||
var source = _random.Pick(sources); | ||
sources.Remove(source); | ||
|
||
var sink = _random.Pick(sinks); | ||
sinks.Remove(sink); | ||
|
||
if (_random.Prob(tech.Comp.EmagSupercritProbability)) | ||
{ | ||
_emag.DoEmagEffect(tech, source); | ||
_emag.DoEmagEffect(tech, sink); | ||
} | ||
|
||
CreateNewLink(tech, source, sink); | ||
} | ||
} | ||
|
||
private void OnPulse(Entity<TechAnomalyComponent> tech, ref AnomalyPulseEvent args) | ||
{ | ||
_signal.InvokePort(tech, tech.Comp.PulsePort); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.