Add FTL arrival visuals (#29402)

* Add FTL arrival visuals

* weh

* Update Content.Shared/Shuttles/Components/FTLComponent.cs

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>

---------

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
This commit is contained in:
metalgearsloth
2024-07-01 16:11:30 +10:00
committed by GitHub
parent 5543689c14
commit b6cf2ce524
10 changed files with 196 additions and 9 deletions

View File

@@ -0,0 +1,82 @@
using System.Numerics;
using Content.Shared.Shuttles.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Shuttles;
/// <summary>
/// Plays a visualization whenever a shuttle is arriving from FTL.
/// </summary>
public sealed class FtlArrivalOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
private EntityLookupSystem _lookups;
private SharedMapSystem _maps;
private SharedTransformSystem _transforms;
private SpriteSystem _sprites;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _protos = default!;
private readonly HashSet<Entity<FtlVisualizerComponent>> _visualizers = new();
private ShaderInstance _shader;
public FtlArrivalOverlay()
{
IoCManager.InjectDependencies(this);
_lookups = _entManager.System<EntityLookupSystem>();
_transforms = _entManager.System<SharedTransformSystem>();
_maps = _entManager.System<SharedMapSystem>();
_sprites = _entManager.System<SpriteSystem>();
_shader = _protos.Index<ShaderPrototype>("unshaded").Instance();
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
{
_visualizers.Clear();
_lookups.GetEntitiesOnMap(args.MapId, _visualizers);
return _visualizers.Count > 0;
}
protected override void Draw(in OverlayDrawArgs args)
{
args.WorldHandle.UseShader(_shader);
foreach (var (uid, comp) in _visualizers)
{
var grid = comp.Grid;
if (!_entManager.TryGetComponent(grid, out MapGridComponent? mapGrid))
continue;
var texture = _sprites.GetFrame(comp.Sprite, TimeSpan.FromSeconds(comp.Elapsed), loop: false);
comp.Elapsed += (float) _timing.FrameTime.TotalSeconds;
// Need to manually transform the viewport in terms of the visualizer entity as the grid isn't in position.
var (_, _, worldMatrix, invMatrix) = _transforms.GetWorldPositionRotationMatrixWithInv(uid);
args.WorldHandle.SetTransform(worldMatrix);
var localAABB = invMatrix.TransformBox(args.WorldBounds);
var tilesEnumerator = _maps.GetLocalTilesEnumerator(grid, mapGrid, localAABB);
while (tilesEnumerator.MoveNext(out var tile))
{
var bounds = _lookups.GetLocalBounds(tile, mapGrid.TileSize);
args.WorldHandle.DrawTextureRect(texture, bounds);
}
}
args.WorldHandle.UseShader(null);
args.WorldHandle.SetTransform(Matrix3x2.Identity);
}
}

View File

@@ -38,9 +38,8 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
private bool _enableShuttlePosition; private bool _enableShuttlePosition;
private EmergencyShuttleOverlay? _overlay; private EmergencyShuttleOverlay? _overlay;
public override void Initialize() private void InitializeEmergency()
{ {
base.Initialize();
SubscribeNetworkEvent<EmergencyShuttlePositionMessage>(OnShuttlePosMessage); SubscribeNetworkEvent<EmergencyShuttlePositionMessage>(OnShuttlePosMessage);
} }

View File

@@ -0,0 +1,21 @@
using Robust.Client.Graphics;
namespace Content.Client.Shuttles.Systems;
public sealed partial class ShuttleSystem
{
[Dependency] private readonly IOverlayManager _overlays = default!;
public override void Initialize()
{
base.Initialize();
InitializeEmergency();
_overlays.AddOverlay(new FtlArrivalOverlay());
}
public override void Shutdown()
{
base.Shutdown();
_overlays.RemoveOverlay<FtlArrivalOverlay>();
}
}

View File

@@ -82,6 +82,8 @@ public sealed partial class ShuttleSystem
private void InitializeFTL() private void InitializeFTL()
{ {
SubscribeLocalEvent<StationPostInitEvent>(OnStationPostInit); SubscribeLocalEvent<StationPostInitEvent>(OnStationPostInit);
SubscribeLocalEvent<FTLComponent, ComponentShutdown>(OnFtlShutdown);
_bodyQuery = GetEntityQuery<BodyComponent>(); _bodyQuery = GetEntityQuery<BodyComponent>();
_buckleQuery = GetEntityQuery<BuckleComponent>(); _buckleQuery = GetEntityQuery<BuckleComponent>();
_beaconQuery = GetEntityQuery<FTLBeaconComponent>(); _beaconQuery = GetEntityQuery<FTLBeaconComponent>();
@@ -98,6 +100,12 @@ public sealed partial class ShuttleSystem
_cfg.OnValueChanged(CCVars.HyperspaceKnockdownTime, time => _hyperspaceKnockdownTime = TimeSpan.FromSeconds(time), true); _cfg.OnValueChanged(CCVars.HyperspaceKnockdownTime, time => _hyperspaceKnockdownTime = TimeSpan.FromSeconds(time), true);
} }
private void OnFtlShutdown(Entity<FTLComponent> ent, ref ComponentShutdown args)
{
Del(ent.Comp.VisualizerEntity);
ent.Comp.VisualizerEntity = null;
}
private void OnStationPostInit(ref StationPostInitEvent ev) private void OnStationPostInit(ref StationPostInitEvent ev)
{ {
// Add all grid maps as ftl destinations that anyone can FTL to. // Add all grid maps as ftl destinations that anyone can FTL to.
@@ -422,8 +430,16 @@ public sealed partial class ShuttleSystem
var comp = entity.Comp1; var comp = entity.Comp1;
comp.StateTime = StartEndTime.FromCurTime(_gameTiming, DefaultArrivalTime); comp.StateTime = StartEndTime.FromCurTime(_gameTiming, DefaultArrivalTime);
comp.State = FTLState.Arriving; comp.State = FTLState.Arriving;
// TODO: Arrival effects
// For now we'll just use the ss13 bubbles but we can do fancier. if (entity.Comp1.VisualizerProto != null)
{
comp.VisualizerEntity = SpawnAtPosition(entity.Comp1.VisualizerProto, entity.Comp1.TargetCoordinates);
var visuals = Comp<FtlVisualizerComponent>(comp.VisualizerEntity.Value);
visuals.Grid = entity.Owner;
Dirty(comp.VisualizerEntity.Value, visuals);
_transform.SetLocalRotation(comp.VisualizerEntity.Value, entity.Comp1.TargetAngle);
_pvs.AddGlobalOverride(comp.VisualizerEntity.Value);
}
_thruster.DisableLinearThrusters(shuttle); _thruster.DisableLinearThrusters(shuttle);
_thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.South); _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.South);

View File

@@ -11,6 +11,7 @@ using Content.Shared.Shuttles.Systems;
using Content.Shared.Throwing; using Content.Shared.Throwing;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.GameStates;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems; using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
@@ -40,6 +41,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
[Dependency] private readonly FixtureSystem _fixtures = default!; [Dependency] private readonly FixtureSystem _fixtures = default!;
[Dependency] private readonly MapLoaderSystem _loader = default!; [Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly MetaDataSystem _metadata = default!;
[Dependency] private readonly PvsOverrideSystem _pvs = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedMapSystem _maps = default!; [Dependency] private readonly SharedMapSystem _maps = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!;

View File

@@ -2,16 +2,16 @@ using Content.Shared.Shuttles.Systems;
using Content.Shared.Tag; using Content.Shared.Tag;
using Content.Shared.Timing; using Content.Shared.Timing;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Shuttles.Components; namespace Content.Shared.Shuttles.Components;
/// <summary> /// <summary>
/// Added to a component when it is queued or is travelling via FTL. /// Added to a component when it is queued or is travelling via FTL.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class FTLComponent : Component public sealed partial class FTLComponent : Component
{ {
// TODO Full game save / add datafields // TODO Full game save / add datafields
@@ -29,13 +29,19 @@ public sealed partial class FTLComponent : Component
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public float TravelTime = 0f; public float TravelTime = 0f;
[DataField]
public EntProtoId? VisualizerProto = "FtlVisualizerEntity";
[DataField, AutoNetworkedField]
public EntityUid? VisualizerEntity;
/// <summary> /// <summary>
/// Coordinates to arrive it: May be relative to another grid (for docking) or map coordinates. /// Coordinates to arrive it: May be relative to another grid (for docking) or map coordinates.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField] [DataField, AutoNetworkedField]
public EntityCoordinates TargetCoordinates; public EntityCoordinates TargetCoordinates;
[DataField] [DataField, AutoNetworkedField]
public Angle TargetAngle; public Angle TargetAngle;
/// <summary> /// <summary>

View File

@@ -0,0 +1,23 @@
using Robust.Shared.GameStates;
using Robust.Shared.Utility;
namespace Content.Shared.Shuttles.Components;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class FtlVisualizerComponent : Component
{
/// <summary>
/// Clientside time tracker for the animation.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float Elapsed;
[DataField(required: true)]
public SpriteSpecifier.Rsi Sprite;
/// <summary>
/// Target grid to pull FTL visualization from.
/// </summary>
[DataField, AutoNetworkedField]
public EntityUid Grid;
}

View File

@@ -0,0 +1,12 @@
- type: entity
id: FtlVisualizerEntity
noSpawn: true
description: Visualizer for shuttles arriving. You shouldn't see this!
components:
- type: FtlVisualizer
sprite:
sprite: /Textures/Effects/medi_holo.rsi
state: medi_holo
- type: Tag
tags:
- HideContextMenu

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,26 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/tgstation/tgstation/tree/217b39cc85e45302d407d5c1ab60809bd9e18987",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "medi_holo",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
}
]
}