diff --git a/Content.Shared/Floofstation/Leash/Components/LeashComponent.cs b/Content.Shared/Floofstation/Leash/Components/LeashComponent.cs index 01922720ceb..20ba744c0a4 100644 --- a/Content.Shared/Floofstation/Leash/Components/LeashComponent.cs +++ b/Content.Shared/Floofstation/Leash/Components/LeashComponent.cs @@ -74,7 +74,7 @@ public sealed partial class LeashComponent : Component public List Leashed = new(); [DataDefinition, Serializable, NetSerializable] - public partial class LeashData + public sealed partial class LeashData { [DataField] public string JointId = string.Empty; diff --git a/Content.Shared/Floofstation/Leash/LeashSystem.cs b/Content.Shared/Floofstation/Leash/LeashSystem.cs index 15bdb0a16d6..fcd77a5994a 100644 --- a/Content.Shared/Floofstation/Leash/LeashSystem.cs +++ b/Content.Shared/Floofstation/Leash/LeashSystem.cs @@ -16,6 +16,8 @@ using Robust.Shared.Map; using Robust.Shared.Network; using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Dynamics.Joints; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using Robust.Shared.Timing; @@ -60,9 +62,9 @@ public override void Shutdown() public override void Update(float frameTime) { - var leashQuery = EntityQueryEnumerator(); + var leashQuery = EntityQueryEnumerator(); - while (leashQuery.MoveNext(out var leashEnt, out var leash)) + while (leashQuery.MoveNext(out var leashEnt, out var leash, out var physics)) { var sourceXForm = Transform(leashEnt); @@ -133,10 +135,11 @@ private void OnJointRemoved(Entity ent, ref JointRemovedEvent ar { var id = args.Joint.ID; if (!ent.Comp.Leashed.TryFirstOrDefault(it => it.JointId == id, out var data) - || !TryComp(GetEntity(data.Pulled), out var leashed)) + || !TryGetEntity(data.Pulled, out var leashedEnt) + || !TryComp(leashedEnt, out var leashed)) return; - RemoveLeash((leashed.Owner, leashed), ent!, false); + RemoveLeash((leashedEnt.Value, leashed), ent!, false); } private void OnGetEquipmentVerbs(Entity ent, ref GetVerbsEvent args) @@ -197,7 +200,7 @@ private void OnAttachDoAfter(Entity ent, ref LeashAttachDo || !CanLeash(ent, (args.Used.Value, leash))) return; - DoLeash(ent, (args.Used.Value, leash), args.Target!.Value); + DoLeash(ent, (args.Used.Value, leash), EntityUid.Invalid); } private void OnDetachDoAfter(Entity ent, ref LeashDetachDoAfterEvent args) @@ -205,7 +208,7 @@ private void OnDetachDoAfter(Entity ent, ref LeashDetachDoAfte if (args.Cancelled || args.Handled || ent.Comp.Puller is not { } leash) return; - RemoveLeash(ent!, leash, true); + RemoveLeash(ent!, leash); } private bool OnRequestPullLeash(ICommonSession? session, EntityCoordinates targetCoords, EntityUid uid) @@ -267,6 +270,19 @@ private bool TryGetLeashTarget(Entity ent, out EntityUid return true; } + private DistanceJoint CreateLeashJoint(string jointId, Entity leash, EntityUid leashTarget) + { + var joint = _joints.CreateDistanceJoint(leash, leashTarget, id: jointId); + joint.CollideConnected = false; + joint.Length = leash.Comp.Length; + joint.MinLength = 0f; + joint.MaxLength = leash.Comp.Length; + joint.Stiffness = 1f; + joint.CollideConnected = true; // This is just for performance reasons and doesn't actually make mobs collide. + + return joint; + } + #endregion #region public api @@ -281,7 +297,7 @@ public bool CanLeash(Entity anchor, Entity && !_xform.IsParentOf(Transform(leashTarget), leash); // google recursion - this makes the game explode for some reason } - public bool TryLeash(Entity anchor, Entity leash, EntityUid user) + public bool TryLeash(Entity anchor, Entity leash, EntityUid user, bool popup = true) { if (!CanLeash(anchor, leash) || !TryGetLeashTarget(anchor!, out var leashTarget)) return false; @@ -304,7 +320,7 @@ public bool TryLeash(Entity anchor, Entity }; var result = _doAfters.TryStartDoAfter(doAfter); - if (result && _net.IsServer) + if (result && _net.IsServer && popup) { (string, object)[] locArgs = [("user", user), ("target", leashTarget), ("anchor", anchor.Owner), ("selfAnchor", anchor.Owner == leashTarget)]; @@ -345,6 +361,12 @@ public bool TryUnleash(Entity leashed, Entity + /// Immediately creates the leash joint between the specified entities and sets up respective components. + /// + /// The anchor entity, usually either target's clothing or the target itself. + /// The leash entity. + /// The entity to which the leash is actually connected. Can be EntityUid.Invalid, then it will be deduced. public void DoLeash(Entity anchor, Entity leash, EntityUid leashTarget) { if (_net.IsClient || leashTarget is { Valid: false } && !TryGetLeashTarget(anchor!, out leashTarget)) @@ -357,14 +379,7 @@ public void DoLeash(Entity anchor, Entity leashedComp.Anchor = anchor; // I'd like to use a chain joint or smth, but it's too hard and oftentimes buggy - lamia is a good bad example of that. - var joint = _joints.CreateDistanceJoint(leash, leashTarget, id: leashedComp.JointId); - joint.CollideConnected = false; - joint.Length = leash.Comp.Length; - joint.MinLength = 0f; - joint.MaxLength = leash.Comp.Length; - joint.Stiffness = 0f; - joint.Damping = 0f; - + var joint = CreateLeashJoint(leashedComp.JointId, leash, leashTarget); var data = new LeashComponent.LeashData(leashedComp.JointId, netLeashTarget) { NextDamage = _timing.CurTime + leash.Comp.DamageInterval