| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- using Content.Client.Rotation;
- using Content.Shared.Buckle;
- using Content.Shared.Buckle.Components;
- using Content.Shared.Rotation;
- using Robust.Client.GameObjects;
- using Robust.Client.Graphics;
- namespace Content.Client.Buckle;
- internal sealed class BuckleSystem : SharedBuckleSystem
- {
- [Dependency] private readonly RotationVisualizerSystem _rotationVisualizerSystem = default!;
- [Dependency] private readonly IEyeManager _eye = default!;
- [Dependency] private readonly SharedTransformSystem _xformSystem = default!;
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent<BuckleComponent, AppearanceChangeEvent>(OnAppearanceChange);
- SubscribeLocalEvent<StrapComponent, MoveEvent>(OnStrapMoveEvent);
- SubscribeLocalEvent<BuckleComponent, BuckledEvent>(OnBuckledEvent);
- SubscribeLocalEvent<BuckleComponent, UnbuckledEvent>(OnUnbuckledEvent);
- }
- private void OnStrapMoveEvent(EntityUid uid, StrapComponent component, ref MoveEvent args)
- {
- // I'm moving this to the client-side system, but for the sake of posterity let's keep this comment:
- // > This is mega cursed. Please somebody save me from Mr Buckle's wild ride
- // The nice thing is its still true, this is quite cursed, though maybe not omega cursed anymore.
- // This code is garbage, it doesn't work with rotated viewports. I need to finally get around to reworking
- // sprite rendering for entity layers & direction dependent sorting.
- // Future notes:
- // Right now this doesn't handle: other grids, other grids rotating, the camera rotation changing, and many other fun rotation specific things
- // The entire thing should be a concern of the engine, or something engine helps to implement properly.
- // Give some of the sprite rotations their own drawdepth, maybe as an offset within the rsi, or something like this
- // And we won't ever need to set the draw depth manually
- if (args.NewRotation == args.OldRotation)
- return;
- if (!TryComp<SpriteComponent>(uid, out var strapSprite))
- return;
- var angle = _xformSystem.GetWorldRotation(uid) + _eye.CurrentEye.Rotation; // Get true screen position, or close enough
- var isNorth = angle.GetCardinalDir() == Direction.North;
- foreach (var buckledEntity in component.BuckledEntities)
- {
- if (!TryComp<BuckleComponent>(buckledEntity, out var buckle))
- continue;
- if (!TryComp<SpriteComponent>(buckledEntity, out var buckledSprite))
- continue;
- if (isNorth)
- {
- // This will only assign if empty, it won't get overwritten by new depth on multiple calls, which do happen easily
- buckle.OriginalDrawDepth ??= buckledSprite.DrawDepth;
- buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
- }
- else if (buckle.OriginalDrawDepth.HasValue)
- {
- buckledSprite.DrawDepth = buckle.OriginalDrawDepth.Value;
- buckle.OriginalDrawDepth = null;
- }
- }
- }
- /// <summary>
- /// Lower the draw depth of the buckled entity without needing for the strap entity to rotate/move.
- /// Only do so when the entity is facing screen-local north
- /// </summary>
- private void OnBuckledEvent(Entity<BuckleComponent> ent, ref BuckledEvent args)
- {
- if (!TryComp<SpriteComponent>(args.Strap, out var strapSprite))
- return;
- if (!TryComp<SpriteComponent>(ent.Owner, out var buckledSprite))
- return;
- var angle = _xformSystem.GetWorldRotation(args.Strap) + _eye.CurrentEye.Rotation; // Get true screen position, or close enough
- if (angle.GetCardinalDir() != Direction.North)
- return;
- ent.Comp.OriginalDrawDepth ??= buckledSprite.DrawDepth;
- buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
- }
- /// <summary>
- /// Was the draw depth of the buckled entity lowered? Reset it upon unbuckling.
- /// </summary>
- private void OnUnbuckledEvent(Entity<BuckleComponent> ent, ref UnbuckledEvent args)
- {
- if (!TryComp<SpriteComponent>(ent.Owner, out var buckledSprite))
- return;
- if (!ent.Comp.OriginalDrawDepth.HasValue)
- return;
- buckledSprite.DrawDepth = ent.Comp.OriginalDrawDepth.Value;
- ent.Comp.OriginalDrawDepth = null;
- }
- private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args)
- {
- if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals))
- return;
- if (!Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
- !buckled ||
- args.Sprite == null)
- {
- _rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation);
- return;
- }
- // Animate strapping yourself to something at a given angle
- // TODO: Dump this when buckle is better
- _rotationVisualizerSystem.AnimateSpriteRotation(uid, args.Sprite, rotVisuals.HorizontalRotation, 0.125f);
- }
- }
|