From 19bd739b0de81b9ed776613c80fdcf995483a726 Mon Sep 17 00:00:00 2001 From: Morshu32 Date: Fri, 18 Dec 2020 20:12:53 +0100 Subject: [PATCH] PreventCollision with strap component while buckled to it (#2694) * AvoidCollision if collided entity is the one that the character is buckled to * Attempt to PreventCollision after the player is unbuckled but still colliding with StrapComponent * Moved PreventCollide to the Shared script. * Add WakeBody to keep updating the physics collision while being on a collidable strap component. * Addressed some of metalgearsloth's suggestions: - Made EntityBuckledTo,IsOnStrapEntityThisFrame and DontCollide not virtual -Made EntityBuckledTo nullable -Don't call update on Paused BuckleComponents -Removed EntityBuckledTo variable declaration in BuckleComponent because it's not needed anymore -Call TryUnbuckle if (!IsOnStrapEntityThisFrame && DontCollide) to set BuckledTo entity to null. * Formatting Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Formatting again :P Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Renamed variable EntityBuckledTo to LastEntityBuckledTo * As per DrSmugLeaf suggestion: Added [ComponentDependency] to the Body variable. Co-authored-by: DrSmugleaf --- .../Components/Buckle/BuckleComponent.cs | 4 ++- .../Components/Buckle/BuckleComponent.cs | 26 ++++++++++++-- .../GameObjects/EntitySystems/BuckleSystem.cs | 8 +++++ .../Buckle/SharedBuckleComponent.cs | 36 ++++++++++++++++--- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs index 491be6c91d..a3020c85bc 100644 --- a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.GameObjects.Components.Buckle; +using Content.Shared.GameObjects.Components.Buckle; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; @@ -27,6 +27,8 @@ namespace Content.Client.GameObjects.Components.Buckle } _buckled = buckle.Buckled; + LastEntityBuckledTo = buckle.LastEntityBuckledTo; + DontCollide = buckle.DontCollide; if (!Owner.TryGetComponent(out SpriteComponent ownerSprite)) { diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 5fef60e9de..d6bdd0fa58 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -27,6 +27,7 @@ using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -49,7 +50,6 @@ namespace Content.Server.GameObjects.Components.Buckle /// [ViewVariables] private float _range; - /// /// The amount of time that must pass for this entity to /// be able to unbuckle after recently buckling. @@ -69,6 +69,7 @@ namespace Content.Server.GameObjects.Components.Buckle public Vector2 BuckleOffset { get; private set; } private StrapComponent? _buckledTo; + /// /// The strap that this component is buckled to. @@ -266,6 +267,8 @@ namespace Content.Server.GameObjects.Components.Buckle AppearanceComponent?.SetData(BuckleVisuals.Buckled, true); BuckledTo = strap; + LastEntityBuckledTo = BuckledTo.Owner.Uid; + DontCollide = true; ReAttach(strap); UpdateBuckleStatus(); @@ -418,8 +421,9 @@ namespace Content.Server.GameObjects.Components.Buckle { drawDepth = BuckledTo.SpriteComponent.DrawDepth - 1; } + - return new BuckleComponentState(Buckled, drawDepth); + return new BuckleComponentState(Buckled, drawDepth, LastEntityBuckledTo, DontCollide); } bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) @@ -427,6 +431,24 @@ namespace Content.Server.GameObjects.Components.Buckle return TryUnbuckle(eventArgs.User); } + + public void Update() + { + if (!DontCollide || Body == null) + return; + + Body.WakeBody(); + + if (!IsOnStrapEntityThisFrame && DontCollide) + { + DontCollide = false; + TryUnbuckle(Owner); + Dirty(); + } + + IsOnStrapEntityThisFrame = false; + } + /// /// Allows the unbuckling of the owning entity through a verb if /// anyone right clicks them. diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs index 1993021296..596aa1c319 100644 --- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs @@ -26,6 +26,14 @@ namespace Content.Server.GameObjects.EntitySystems SubscribeLocalEvent(ContainerModified); } + public override void Update(float frameTime) + { + foreach (var comp in ComponentManager.EntityQuery(false)) + { + comp.Update(); + } + } + public override void Shutdown() { base.Shutdown(); diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index 221d1cb845..068ce878c7 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -1,30 +1,54 @@ -using System; +#nullable enable +using System; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.ComponentDependencies; +using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Physics; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Buckle { - public abstract class SharedBuckleComponent : Component, IActionBlocker, IEffectBlocker, IDraggable + public abstract class SharedBuckleComponent : Component, IActionBlocker, IEffectBlocker, IDraggable, ICollideSpecial { public sealed override string Name => "Buckle"; public sealed override uint? NetID => ContentNetIDs.BUCKLE; - /// /// True if the entity is buckled, false otherwise. /// public abstract bool Buckled { get; } + public EntityUid? LastEntityBuckledTo { get; set; } + public bool IsOnStrapEntityThisFrame { get; set; } + public bool DontCollide { get; set; } public abstract bool TryBuckle(IEntity user, IEntity to); + [ComponentDependency] protected IPhysicsComponent? Body; + + bool ICollideSpecial.PreventCollide(IPhysBody collidedwith) + { + if (collidedwith.Entity.Uid == LastEntityBuckledTo) + { + IsOnStrapEntityThisFrame = true; + return Buckled || DontCollide; + } + + return false; + } + bool IActionBlocker.CanMove() { return !Buckled; } + public override void Initialize() + { + base.Initialize(); + Owner.TryGetComponent(out Body); + } bool IActionBlocker.CanChangeDirection() { @@ -50,13 +74,17 @@ namespace Content.Shared.GameObjects.Components.Buckle [Serializable, NetSerializable] public sealed class BuckleComponentState : ComponentState { - public BuckleComponentState(bool buckled, int? drawDepth) : base(ContentNetIDs.BUCKLE) + public BuckleComponentState(bool buckled, int? drawDepth, EntityUid? lastEntityBuckledTo, bool dontCollide) : base(ContentNetIDs.BUCKLE) { Buckled = buckled; DrawDepth = drawDepth; + LastEntityBuckledTo = lastEntityBuckledTo; + DontCollide = dontCollide; } public bool Buckled { get; } + public EntityUid? LastEntityBuckledTo { get; } + public bool DontCollide { get; } public int? DrawDepth; }