BuckleSystem: buckled/strapped event on startup (#44878)

This commit is contained in:
Whatstone 2026-07-31 14:14:30 -04:00 • committed by GitHub
parent bb5f8d696a
commit d7f0d85780
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 68 additions and 58 deletions

View file

@ -15,26 +15,12 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
[Dependency] private SharedTransformSystem _xformSystem = default!;
[Dependency] private SpriteSystem _sprite = default!;
public override void Initialize()
{
base.Initialize();
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
SubscribeLocalEvent<BuckleComponent, AppearanceChangeEvent>(OnAppearanceChange);
SubscribeLocalEvent<StrapComponent, MoveEvent>(OnStrapMoveEvent);
SubscribeLocalEvent<BuckleComponent, BuckledEvent>(OnBuckledEvent);
SubscribeLocalEvent<BuckleComponent, UnbuckledEvent>(OnUnbuckledEvent);
SubscribeLocalEvent<BuckleComponent, AttemptMobCollideEvent>(OnMobCollide);
}
#region Event Handlers
private void OnMobCollide(Entity<BuckleComponent> ent, ref AttemptMobCollideEvent args)
{
if (ent.Comp.Buckled)
{
args.Cancelled = true;
}
}
private void OnStrapMoveEvent(EntityUid uid, StrapComponent component, ref MoveEvent args)
[SubscribeLocalEvent]
private void OnStrapMoveEvent(Entity<StrapComponent> ent, 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
@ -49,24 +35,24 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
// 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 (!component.ModifyBuckleDrawDepth)
if (!ent.Comp.ModifyBuckleDrawDepth)
return;
if (args.NewRotation == args.OldRotation)
return;
if (!TryComp<SpriteComponent>(uid, out var strapSprite))
if (!_spriteQuery.TryComp(ent, out SpriteComponent? strapSprite))
return;
var angle = _xformSystem.GetWorldRotation(uid) + _eye.CurrentEye.Rotation; // Get true screen position, or close enough
var angle = _xformSystem.GetWorldRotation(ent) + _eye.CurrentEye.Rotation; // Get true screen position, or close enough
var isNorth = angle.GetCardinalDir() == Direction.North;
foreach (var buckledEntity in component.BuckledEntities)
foreach (var buckledEntity in ent.Comp.BuckledEntities)
{
if (!TryComp<BuckleComponent>(buckledEntity, out var buckle))
continue;
if (!TryComp<SpriteComponent>(buckledEntity, out var buckledSprite))
if (!_spriteQuery.TryComp(buckledEntity, out SpriteComponent? buckledSprite))
continue;
if (isNorth)
@ -83,19 +69,29 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
}
}
[SubscribeLocalEvent]
private void OnMobCollide(Entity<BuckleComponent> ent, ref AttemptMobCollideEvent args)
{
if (ent.Comp.Buckled)
{
args.Cancelled = true;
}
}
/// <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>
[SubscribeLocalEvent]
private void OnBuckledEvent(Entity<BuckleComponent> ent, ref BuckledEvent args)
{
if (!args.Strap.Comp.ModifyBuckleDrawDepth)
return;
if (!TryComp<SpriteComponent>(args.Strap, out var strapSprite))
if (!_spriteQuery.TryComp(args.Strap, out SpriteComponent? strapSprite))
return;
if (!TryComp<SpriteComponent>(ent.Owner, out var buckledSprite))
if (!_spriteQuery.TryComp(ent.Owner, out SpriteComponent? buckledSprite))
return;
var angle = _xformSystem.GetWorldRotation(args.Strap) + _eye.CurrentEye.Rotation; // Get true screen position, or close enough
@ -110,12 +106,13 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
/// <summary>
/// Was the draw depth of the buckled entity lowered? Reset it upon unbuckling.
/// </summary>
[SubscribeLocalEvent]
private void OnUnbuckledEvent(Entity<BuckleComponent> ent, ref UnbuckledEvent args)
{
if (!args.Strap.Comp.ModifyBuckleDrawDepth)
return;
if (!TryComp<SpriteComponent>(ent.Owner, out var buckledSprite))
if (!_spriteQuery.TryComp(ent.Owner, out SpriteComponent? buckledSprite))
return;
if (!ent.Comp.OriginalDrawDepth.HasValue)
@ -125,21 +122,23 @@ internal sealed partial class BuckleSystem : SharedBuckleSystem
ent.Comp.OriginalDrawDepth = null;
}
private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args)
[SubscribeLocalEvent]
private void OnAppearanceChange(Entity<BuckleComponent> ent, ref AppearanceChangeEvent args)
{
if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals))
if (!TryComp<RotationVisualsComponent>(ent, out var rotVisuals))
return;
if (!Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
if (!Appearance.TryGetData<bool>(ent, BuckleVisuals.Buckled, out var buckled, args.Component) ||
!buckled ||
args.Sprite == null)
{
_rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation);
_rotationVisualizerSystem.SetHorizontalAngle((ent, 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);
_rotationVisualizerSystem.AnimateSpriteRotation(ent, args.Sprite, rotVisuals.HorizontalRotation, 0.125f);
}
#endregion Event Handlers
}

View file

@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Content.Shared.Buckle.Components;
using Content.Shared.Construction;
using Content.Shared.Destructible;
@ -12,58 +12,69 @@ public abstract partial class SharedBuckleSystem
{
private void InitializeStrap()
{
SubscribeLocalEvent<StrapComponent, ComponentStartup>(OnStrapStartup);
SubscribeLocalEvent<StrapComponent, ComponentShutdown>(OnStrapShutdown);
SubscribeLocalEvent<StrapComponent, EntityTerminatingEvent>(OnStrapTerminating);
SubscribeLocalEvent<StrapComponent, ComponentRemove>((e, c, _) => StrapRemoveAll(e, c));
SubscribeLocalEvent<StrapComponent, ContainerGettingInsertedAttemptEvent>(OnStrapContainerGettingInsertedAttempt);
SubscribeLocalEvent<StrapComponent, DestructionEventArgs>((e, c, _) => StrapRemoveAll(e, c));
SubscribeLocalEvent<StrapComponent, BreakageEventArgs>((e, c, _) => StrapRemoveAll(e, c));
SubscribeLocalEvent<StrapComponent, FoldAttemptEvent>(OnAttemptFold);
SubscribeLocalEvent<StrapComponent, MachineDeconstructedEvent>((e, c, _) => StrapRemoveAll(e, c));
SubscribeLocalEvent<StrapComponent, ComponentRemove>((e, ref _) => StrapRemoveAll(e));
SubscribeLocalEvent<StrapComponent, DestructionEventArgs>((e, ref _) => StrapRemoveAll(e));
SubscribeLocalEvent<StrapComponent, BreakageEventArgs>((e, ref _) => StrapRemoveAll(e));
SubscribeLocalEvent<StrapComponent, MachineDeconstructedEvent>((e, ref _) => StrapRemoveAll(e));
}
private void OnStrapStartup(EntityUid uid, StrapComponent component, ComponentStartup args)
[SubscribeLocalEvent]
private void OnStrapStartup(Entity<StrapComponent> ent, ref ComponentStartup args)
{
Appearance.SetData(uid, StrapVisuals.State, component.BuckledEntities.Count != 0);
Appearance.SetData(ent, StrapVisuals.State, ent.Comp.BuckledEntities.Count != 0);
// Raise events on anything that starts buckled.
foreach (var buckle in ent.Comp.BuckledEntities)
{
if (!TryComp<BuckleComponent>(buckle, out var buckleComp))
continue;
var ev = new StrappedEvent(ent, (buckle, buckleComp));
RaiseLocalEvent(ent, ref ev);
var gotEv = new BuckledEvent(ent, (buckle, buckleComp));
RaiseLocalEvent(buckle, ref gotEv);
}
}
private void OnStrapShutdown(EntityUid uid, StrapComponent component, ComponentShutdown args)
[SubscribeLocalEvent]
private void OnStrapShutdown(Entity<StrapComponent> ent, ref ComponentShutdown args)
{
if (!TerminatingOrDeleted(uid))
StrapRemoveAll(uid, component);
if (!TerminatingOrDeleted(ent))
StrapRemoveAll(ent);
}
private void OnStrapTerminating(Entity<StrapComponent> entity, ref EntityTerminatingEvent args)
[SubscribeLocalEvent]
private void OnStrapTerminating(Entity<StrapComponent> ent, ref EntityTerminatingEvent args)
{
StrapRemoveAll(entity, entity.Comp);
StrapRemoveAll(ent);
}
private void OnStrapContainerGettingInsertedAttempt(EntityUid uid, StrapComponent component, ContainerGettingInsertedAttemptEvent args)
[SubscribeLocalEvent]
private void OnStrapContainerGettingInsertedAttempt(Entity<StrapComponent> ent, ref ContainerGettingInsertedAttemptEvent args)
{
// If someone is attempting to put this item inside of a backpack, ensure that it has no entities strapped to it.
if (args.Container.ID == StorageComponent.ContainerId && component.BuckledEntities.Count != 0)
if (args.Container.ID == StorageComponent.ContainerId && ent.Comp.BuckledEntities.Count != 0)
args.Cancel();
}
private void OnAttemptFold(EntityUid uid, StrapComponent component, ref FoldAttemptEvent args)
[SubscribeLocalEvent]
private void OnAttemptFold(Entity<StrapComponent> ent, ref FoldAttemptEvent args)
{
if (args.Cancelled)
return;
args.Cancelled = component.BuckledEntities.Count != 0;
args.Cancelled = ent.Comp.BuckledEntities.Count != 0;
}
/// <summary>
/// Remove everything attached to the strap
/// </summary>
private void StrapRemoveAll(EntityUid uid, StrapComponent strapComp)
private void StrapRemoveAll(Entity<StrapComponent> ent)
{
foreach (var entity in strapComp.BuckledEntities.ToArray())
foreach (var buckle in ent.Comp.BuckledEntities.ToArray())
{
Unbuckle(entity, entity);
Unbuckle(buckle, buckle);
}
}
@ -94,6 +105,6 @@ public abstract partial class SharedBuckleSystem
Dirty(strapUid, strapComp);
if (!enabled)
StrapRemoveAll(strapUid, strapComp);
StrapRemoveAll((strapUid, strapComp));
}
}