More rotatability (#4067)

* Make barstools, PA components, and radiation collectors rotatable.

Making barstools rotatable is so that people can spin on the barstool. (RP moment.)

The other two are more "functional" changes for assembling a PA.

* Allow rotating a rotate-while-anchored object if you're buckled to it.

Barstool spinny

* Fix bug with rotation of an object that someone is buckled to

* BuckleSystem: Efficiency improvements with directed events

* Don't need to unsubscribe anymore from events, so in BuckleSystem, just don't
This commit is contained in:
20kdc
2021-05-27 11:51:14 +01:00
committed by GitHub
parent 79a13f32e7
commit c7f104cd93
6 changed files with 60 additions and 39 deletions

View File

@@ -43,7 +43,7 @@ namespace Content.Client.GameObjects.Components.Buckle
return; return;
} }
if (!_buckled && _originalDrawDepth.HasValue) if (_originalDrawDepth.HasValue && !buckle.DrawDepth.HasValue)
{ {
ownerSprite.DrawDepth = _originalDrawDepth.Value; ownerSprite.DrawDepth = _originalDrawDepth.Value;
_originalDrawDepth = null; _originalDrawDepth = null;

View File

@@ -20,24 +20,19 @@ namespace Content.Server.GameObjects.EntitySystems
UpdatesAfter.Add(typeof(InteractionSystem)); UpdatesAfter.Add(typeof(InteractionSystem));
UpdatesAfter.Add(typeof(InputSystem)); UpdatesAfter.Add(typeof(InputSystem));
SubscribeLocalEvent<MoveEvent>(MoveEvent); SubscribeLocalEvent<BuckleComponent, MoveEvent>(MoveEvent);
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(ContainerModified);
SubscribeLocalEvent<EntRemovedFromContainerMessage>(ContainerModified); SubscribeLocalEvent<StrapComponent, RotateEvent>(RotateEvent);
SubscribeLocalEvent<BuckleComponent, EntInsertedIntoContainerMessage>(ContainerModifiedBuckle);
SubscribeLocalEvent<StrapComponent, EntInsertedIntoContainerMessage>(ContainerModifiedStrap);
SubscribeLocalEvent<BuckleComponent, EntRemovedFromContainerMessage>(ContainerModifiedBuckle);
SubscribeLocalEvent<StrapComponent, EntRemovedFromContainerMessage>(ContainerModifiedStrap);
SubscribeLocalEvent<BuckleComponent, AttackHandEvent>(HandleAttackHand); SubscribeLocalEvent<BuckleComponent, AttackHandEvent>(HandleAttackHand);
} }
public override void Shutdown()
{
base.Shutdown();
UnsubscribeLocalEvent<MoveEvent>();
UnsubscribeLocalEvent<EntInsertedIntoContainerMessage>();
UnsubscribeLocalEvent<EntRemovedFromContainerMessage>();
UnsubscribeLocalEvent<BuckleComponent, AttackHandEvent>(HandleAttackHand);
}
private void HandleAttackHand(EntityUid uid, BuckleComponent component, AttackHandEvent args) private void HandleAttackHand(EntityUid uid, BuckleComponent component, AttackHandEvent args)
{ {
args.Handled = component.TryUnbuckle(args.User); args.Handled = component.TryUnbuckle(args.User);
@@ -51,13 +46,8 @@ namespace Content.Server.GameObjects.EntitySystems
} }
} }
private void MoveEvent(MoveEvent ev) private void MoveEvent(EntityUid uid, BuckleComponent buckle, MoveEvent ev)
{ {
if (!ev.Sender.TryGetComponent(out BuckleComponent? buckle))
{
return;
}
var strap = buckle.BuckledTo; var strap = buckle.BuckledTo;
if (strap == null) if (strap == null)
@@ -75,25 +65,35 @@ namespace Content.Server.GameObjects.EntitySystems
buckle.TryUnbuckle(buckle.Owner, true); buckle.TryUnbuckle(buckle.Owner, true);
} }
private void ContainerModified(ContainerModifiedMessage message) private void RotateEvent(EntityUid uid, StrapComponent strap, RotateEvent ev)
{ {
// Not returning is necessary in case an entity has both a buckle and strap component // On rotation of a strap, reattach all buckled entities.
if (message.Entity.TryGetComponent(out BuckleComponent? buckle)) // This fixes buckle offsets and draw depths.
foreach (var buckledEntity in strap.BuckledEntities)
{ {
ContainerModifiedReAttach(buckle, buckle.BuckledTo); if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled))
}
if (message.Entity.TryGetComponent(out StrapComponent? strap))
{
foreach (var buckledEntity in strap.BuckledEntities)
{ {
if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled)) continue;
{
continue;
}
ContainerModifiedReAttach(buckled, strap);
} }
buckled.ReAttach(strap);
buckled.Dirty();
}
}
private void ContainerModifiedBuckle(EntityUid uid, BuckleComponent buckle, ContainerModifiedMessage message)
{
ContainerModifiedReAttach(buckle, buckle.BuckledTo);
}
private void ContainerModifiedStrap(EntityUid uid, StrapComponent strap, ContainerModifiedMessage message)
{
foreach (var buckledEntity in strap.BuckledEntities)
{
if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled))
{
continue;
}
ContainerModifiedReAttach(buckled, strap);
} }
} }

View File

@@ -4,10 +4,12 @@ using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Pulling; using Content.Server.GameObjects.Components.Pulling;
using Content.Server.GameObjects.Components.Buckle;
using Content.Server.GameObjects.Components.Timing; using Content.Server.GameObjects.Components.Timing;
using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Rotatable;
using Content.Shared.GameObjects.EntitySystemMessages; using Content.Shared.GameObjects.EntitySystemMessages;
using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
@@ -389,12 +391,27 @@ namespace Content.Server.GameObjects.EntitySystems.Click
private void ClickFace(IEntity player, EntityCoordinates coordinates) private void ClickFace(IEntity player, EntityCoordinates coordinates)
{ {
var diff = coordinates.ToMapPos(EntityManager) - player.Transform.MapPosition.Position;
if (diff.LengthSquared <= 0.01f)
return;
var diffAngle = Angle.FromWorldVec(diff);
if (ActionBlockerSystem.CanChangeDirection(player)) if (ActionBlockerSystem.CanChangeDirection(player))
{ {
var diff = coordinates.ToMapPos(EntityManager) - player.Transform.MapPosition.Position; player.Transform.LocalRotation = diffAngle;
if (diff.LengthSquared > 0.01f) }
else
{
if (player.TryGetComponent(out BuckleComponent? buckle) && (buckle.BuckledTo != null))
{ {
player.Transform.LocalRotation = Angle.FromWorldVec(diff); // We're buckled to another object. Is that object rotatable?
if (buckle.BuckledTo!.Owner.TryGetComponent(out SharedRotatableComponent? rotatable) && rotatable.RotateWhileAnchored)
{
// Note the assumption that even if unanchored, player can only do spinnychair with an "independent wheel".
// (Since the player being buckled to it holds it down with their weight.)
// This is logically equivalent to RotateWhileAnchored.
// Barstools and office chairs have independent wheels, while regular chairs don't.
rotatable.Owner.Transform.LocalRotation = diffAngle;
}
} }
} }
} }

View File

@@ -89,6 +89,8 @@
id: StoolBar id: StoolBar
parent: SeatBase parent: SeatBase
components: components:
- type: Rotatable
rotateWhileAnchored: true
- type: Anchorable - type: Anchorable
- type: Sprite - type: Sprite
state: bar_stool state: bar_stool

View File

@@ -6,6 +6,7 @@
components: components:
- type: InteractionOutline - type: InteractionOutline
- type: Anchorable - type: Anchorable
- type: Rotatable
- type: Physics - type: Physics
bodyType: Static bodyType: Static
fixtures: fixtures:

View File

@@ -40,4 +40,5 @@
nodeGroupID: HVPower nodeGroupID: HVPower
- type: RadiationCollector - type: RadiationCollector
- type: Anchorable - type: Anchorable
- type: Rotatable
- type: Pullable - type: Pullable