mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-06-09 13:26:34 +02:00
2ca5d9d81a
* Initial commit * Added pods * Transit tubes should no longer connect with disposal pipes * Updated the transit tube sprites * Revisited how the transit tubes work * Fixing merge conflict * Updated sprites * Simplified disposal component collections and updated yaml * Moved the majority of the disposals code to Shared * Move disposed ents via physics * Disposal unit now use generic visualizers * Followers of disposed entities have predicted movement * Made BeingDisposedSystem shared * Added documentation for some components * Code clean up * Removed unneeded container entries, tubes use directions instead of angles * Many EntityUid/Comp -> Entity<Comp> changes * Updated DisposableSystem * Review of DisposalTubeSystem * Review of DisposalUnitSystem * Review of DisposalSignalRouterSystem * Unit updates * Fixing merge conflict * Merge conflict resolved * Re-organization of systems and components * Allow trapped entities to escape endless loops * Fix for item ejection * UI updates * Minor tweak * Fixes for transit tubes * Removed placeholder sprite * Removed transit tubes (for now) * Moved exit stun time to DisposalHolderComponent * Added a limit on the amount of damage that can sustained from disposals travel * Fix for PVS-related sound issues * Added a limit on the number of entities that can be inserted into units * Clean up * Undid file scoping * Fixed test fail * Fixed test fail * Increased min default capacity of disposal units * Fixed audio spam occurring when dumping multiple items into a disposal unit * Tile prying now occurs whenever exiting an open pipe * Prevent attacking and interactions while traveling through disposals * Added generic verbs for entering/exiting disposal units * Fixed UI prediction bug * Bug fixes * Small improvements * Moved the disposal holder prototype from the disposal entry to the unit * Minor clean up * Added support for a disposal holder despawn effect * Added prediction guard * Test fail fix * Re-added new escape behavior * Removed outdated PVS code * Clean up * More escape behavior changes * More clean up * Updated exit selection logic * Bug fix * More clean up * Split up disposal unit code * Cleaned up disposal units some more * Adjusted exit throw distance * Capitalized disposal and mailing unit window titles * Bug fixes * Taggers and routers show existing tags when the UI opens * Fixed test fail * test fail fix * Minor performance improvement * Minor improvement in pathing * merge conflicts * Fix heisentest * Fixed mispredict * Updated system referencing conventions * Updated to account for changes made to the code * Attempting to fix submodule issue * Addressing test fails * Additional fixes for tests * Addressing reviewer comments * Cleaned up exit randomization * T-ray can see disposal pipes when in 'pipe' mode * Fix for flush animation flickering * mild thing * fix both --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
244 lines
9.1 KiB
C#
244 lines
9.1 KiB
C#
using Content.Client.Items;
|
|
using Content.Client.Items.UI;
|
|
using Content.Client.Message;
|
|
using Content.Client.Power.Visualizers;
|
|
using Content.Client.Stylesheets;
|
|
using Content.Shared.Atmos.Components;
|
|
using Content.Shared.Disposal.Tube;
|
|
using Content.Shared.Input;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.SubFloor;
|
|
using Robust.Client.Animations;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Input;
|
|
using Robust.Client.Player;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Client.SubFloor;
|
|
|
|
public sealed partial class TrayScannerSystem : SharedTrayScannerSystem
|
|
{
|
|
[Dependency] private IGameTiming _timing = default!;
|
|
[Dependency] private IPlayerManager _player = default!;
|
|
[Dependency] private AnimationPlayerSystem _animation = default!;
|
|
[Dependency] private EntityLookupSystem _lookup = default!;
|
|
[Dependency] private InventorySystem _inventory = default!;
|
|
[Dependency] private SharedAppearanceSystem _appearance = default!;
|
|
[Dependency] private SharedTransformSystem _transform = default!;
|
|
[Dependency] private SpriteSystem _sprite = default!;
|
|
[Dependency] private TrayScanRevealSystem _trayScanReveal = default!;
|
|
[Dependency] private IInputManager _inputManager = default!;
|
|
[Dependency] private EntityQuery<TrayScannerComponent> _trayScannerQuery = default!;
|
|
[Dependency] private EntityQuery<SubFloorHideComponent> _subFloorHideQuery = default!;
|
|
|
|
private const string TRayAnimationKey = "trays";
|
|
private const double AnimationLength = 0.3;
|
|
|
|
public const LookupFlags Flags = LookupFlags.Static | LookupFlags.Sundries | LookupFlags.Approximate;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
Subs.ItemStatus<TrayScannerComponent>(OnCollectItemStatus);
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
if (!_timing.IsFirstTimePredicted)
|
|
return;
|
|
|
|
// TODO: Multiple viewports or w/e
|
|
var player = _player.LocalEntity;
|
|
|
|
if (!TryComp(player, out TransformComponent? playerXform))
|
|
return;
|
|
|
|
var playerPos = _transform.GetWorldPosition(playerXform);
|
|
var playerMap = playerXform.MapID;
|
|
var range = 0f;
|
|
var mode = TrayScannerMode.All;
|
|
HashSet<Entity<SubFloorHideComponent>> inRange;
|
|
|
|
// TODO: Should probably sub to player attached changes / inventory changes but inventory's
|
|
// API is extremely skrungly. If this ever shows up on dottrace ping me and laugh.
|
|
var canSee = false;
|
|
|
|
foreach (var item in _inventory.GetHandOrInventoryEntities(player.Value, SlotFlags.POCKET))
|
|
{
|
|
if (!_trayScannerQuery.TryGetComponent(item, out var scanner) || !scanner.Enabled)
|
|
continue;
|
|
|
|
range = MathF.Max(scanner.Range, range);
|
|
mode = scanner.Mode;
|
|
canSee = true;
|
|
break;
|
|
}
|
|
|
|
inRange = new HashSet<Entity<SubFloorHideComponent>>();
|
|
|
|
if (canSee)
|
|
{
|
|
var entitiesInRange = new HashSet<Entity<SubFloorHideComponent>>();
|
|
_lookup.GetEntitiesInRange(playerMap, playerPos, range, entitiesInRange, flags: Flags);
|
|
|
|
foreach (var (uid, comp) in entitiesInRange)
|
|
{
|
|
if (!MatchesMode(uid, mode))
|
|
continue;
|
|
|
|
inRange.Add((uid, comp));
|
|
|
|
if (comp.IsUnderCover || _trayScanReveal.IsUnderRevealingEntity(uid))
|
|
EnsureComp<TrayRevealedComponent>(uid);
|
|
}
|
|
}
|
|
|
|
var revealedQuery = AllEntityQuery<TrayRevealedComponent, SpriteComponent>();
|
|
|
|
while (revealedQuery.MoveNext(out var uid, out _, out var sprite))
|
|
{
|
|
// Revealing
|
|
// Add buffer range to avoid flickers.
|
|
if (_subFloorHideQuery.TryGetComponent(uid, out var subfloor) &&
|
|
inRange.Contains((uid, subfloor)))
|
|
{
|
|
// Due to the fact client is predicting this server states will reset it constantly
|
|
if ((!_appearance.TryGetData(uid, SubFloorVisuals.ScannerRevealed, out bool value) || !value) &&
|
|
sprite.Color.A > SubfloorRevealAlpha)
|
|
{
|
|
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(0f));
|
|
}
|
|
|
|
SetRevealed(uid, true);
|
|
|
|
if (sprite.Color.A >= SubfloorRevealAlpha || _animation.HasRunningAnimation(uid, TRayAnimationKey))
|
|
continue;
|
|
|
|
_animation.Play(uid, new Animation()
|
|
{
|
|
Length = TimeSpan.FromSeconds(AnimationLength),
|
|
AnimationTracks =
|
|
{
|
|
new AnimationTrackComponentProperty()
|
|
{
|
|
ComponentType = typeof(SpriteComponent),
|
|
Property = nameof(SpriteComponent.Color),
|
|
KeyFrames =
|
|
{
|
|
new AnimationTrackProperty.KeyFrame(sprite.Color.WithAlpha(0f), 0f),
|
|
new AnimationTrackProperty.KeyFrame(sprite.Color.WithAlpha(SubfloorRevealAlpha), (float) AnimationLength)
|
|
}
|
|
}
|
|
}
|
|
}, TRayAnimationKey);
|
|
}
|
|
// Hiding
|
|
else
|
|
{
|
|
// Hidden completely so unreveal and reset the alpha.
|
|
if (sprite.Color.A <= 0f)
|
|
{
|
|
SetRevealed(uid, false);
|
|
RemCompDeferred<TrayRevealedComponent>(uid);
|
|
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(1f));
|
|
continue;
|
|
}
|
|
|
|
SetRevealed(uid, true);
|
|
|
|
if (_animation.HasRunningAnimation(uid, TRayAnimationKey))
|
|
continue;
|
|
|
|
_animation.Play(uid, new Animation()
|
|
{
|
|
Length = TimeSpan.FromSeconds(AnimationLength),
|
|
AnimationTracks =
|
|
{
|
|
new AnimationTrackComponentProperty()
|
|
{
|
|
ComponentType = typeof(SpriteComponent),
|
|
Property = nameof(SpriteComponent.Color),
|
|
KeyFrames =
|
|
{
|
|
new AnimationTrackProperty.KeyFrame(sprite.Color, 0f),
|
|
new AnimationTrackProperty.KeyFrame(sprite.Color.WithAlpha(0f), (float) AnimationLength)
|
|
}
|
|
}
|
|
}
|
|
}, TRayAnimationKey);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetRevealed(EntityUid uid, bool value)
|
|
{
|
|
_appearance.SetData(uid, SubFloorVisuals.ScannerRevealed, value);
|
|
}
|
|
|
|
private bool MatchesMode(EntityUid uid, TrayScannerMode mode)
|
|
{
|
|
return mode switch
|
|
{
|
|
TrayScannerMode.All => true,
|
|
TrayScannerMode.Wiring => HasComp<CableVisualizerComponent>(uid),
|
|
TrayScannerMode.Piping => HasComp<AtmosPipeLayersComponent>(uid) || HasComp<DisposalTubeComponent>(uid),
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
#region UI
|
|
private Control OnCollectItemStatus(Entity<TrayScannerComponent> entity)
|
|
{
|
|
_inputManager.TryGetKeyBinding((ContentKeyFunctions.AltUseItemInHand), out var binding);
|
|
return new StatusControl(entity, binding?.GetKeyString() ?? "");
|
|
}
|
|
|
|
private sealed class StatusControl : PollingItemStatusControl<StatusControl.TRayData>
|
|
{
|
|
private readonly RichTextLabel _label;
|
|
private readonly TrayScannerComponent _scanner;
|
|
private readonly string _keyBindingName;
|
|
|
|
public StatusControl(TrayScannerComponent scanner, string keyBindingName)
|
|
{
|
|
_scanner = scanner;
|
|
_keyBindingName = keyBindingName;
|
|
_label = new RichTextLabel { StyleClasses = { StyleClass.ItemStatus } };
|
|
AddChild(_label);
|
|
}
|
|
|
|
protected override TRayData PollData()
|
|
{
|
|
return new TRayData(_scanner.Enabled, _scanner.Mode);
|
|
}
|
|
|
|
protected override void Update(in TRayData data)
|
|
{
|
|
if (!data.Enabled)
|
|
{
|
|
_label.SetMarkup(string.Empty);
|
|
return;
|
|
}
|
|
|
|
var modeLocString = data.Mode switch
|
|
{
|
|
TrayScannerMode.All => "tray-scanner-examine-mode-all",
|
|
TrayScannerMode.Wiring => "tray-scanner-examine-mode-wiring",
|
|
TrayScannerMode.Piping => "tray-scanner-examine-mode-piping",
|
|
_ => "",
|
|
};
|
|
|
|
_label.SetMarkup(Robust.Shared.Localization.Loc.GetString("tray-scanner-item-status-label",
|
|
("mode", Robust.Shared.Localization.Loc.GetString(modeLocString)),
|
|
("keybinding", _keyBindingName)));
|
|
}
|
|
|
|
public readonly record struct TRayData(bool Enabled, TrayScannerMode Mode);
|
|
}
|
|
#endregion
|
|
}
|