]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Rework the way held items scatter when holder is knocked down (#36232)
authorTayrtahn <tayrtahn@gmail.com>
Mon, 31 Mar 2025 22:00:04 +0000 (18:00 -0400)
committerGitHub <noreply@github.com>
Mon, 31 Mar 2025 22:00:04 +0000 (15:00 -0700)
* Redo drop held items math

* Don't assume the holder has a PhysicsComponent

* Assume infinite mass for held items with no PhysicsComponent

* Switch to EntityQuery for PhysicsComponent

* The micro-est of optimizations

* use NextAngle

* Might as well do that outside the loop

Content.Server/Hands/Systems/HandsSystem.cs

index 41f582cde827f4830f067b177662d261c0dddbc3..1e8e012c5226ba3d6dacbf6f6a6f2917cf1c0cb9 100644 (file)
@@ -39,6 +39,15 @@ namespace Content.Server.Hands.Systems
         [Dependency] private readonly PullingSystem _pullingSystem = default!;
         [Dependency] private readonly ThrowingSystem _throwingSystem = default!;
 
+        private EntityQuery<PhysicsComponent> _physicsQuery;
+
+        /// <summary>
+        /// Items dropped when the holder falls down will be launched in
+        /// a direction offset by up to this many degrees from the holder's
+        /// movement direction.
+        /// </summary>
+        private const float DropHeldItemsSpread = 45;
+
         public override void Initialize()
         {
             base.Initialize();
@@ -60,6 +69,8 @@ namespace Content.Server.Hands.Systems
             CommandBinds.Builder
                 .Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem))
                 .Register<HandsSystem>();
+
+            _physicsQuery = GetEntityQuery<PhysicsComponent>();
         }
 
         public override void Shutdown()
@@ -234,13 +245,13 @@ namespace Content.Server.Hands.Systems
 
         private void OnDropHandItems(Entity<HandsComponent> entity, ref DropHandItemsEvent args)
         {
-            var direction = EntityManager.TryGetComponent(entity, out PhysicsComponent? comp) ? comp.LinearVelocity / 50 : Vector2.Zero;
-            var dropAngle = _random.NextFloat(0.8f, 1.2f);
+            // If the holder doesn't have a physics component, they ain't moving
+            var holderVelocity = _physicsQuery.TryComp(entity, out var physics) ? physics.LinearVelocity : Vector2.Zero;
+            var spreadMaxAngle = Angle.FromDegrees(DropHeldItemsSpread);
 
             var fellEvent = new FellDownEvent(entity);
             RaiseLocalEvent(entity, fellEvent, false);
 
-            var worldRotation = TransformSystem.GetWorldRotation(entity).ToVec();
             foreach (var hand in entity.Comp.Hands.Values)
             {
                 if (hand.HeldEntity is not EntityUid held)
@@ -255,10 +266,26 @@ namespace Content.Server.Hands.Systems
                 if (!TryDrop(entity, hand, null, checkActionBlocker: false, handsComp: entity.Comp))
                     continue;
 
+                // Rotate the item's throw vector a bit for each item
+                var angleOffset = _random.NextAngle(-spreadMaxAngle, spreadMaxAngle);
+                // Rotate the holder's velocity vector by the angle offset to get the item's velocity vector
+                var itemVelocity = angleOffset.RotateVec(holderVelocity);
+                // Decrease the distance of the throw by a random amount
+                itemVelocity *= _random.NextFloat(1f);
+                // Heavier objects don't get thrown as far
+                // If the item doesn't have a physics component, it isn't going to get thrown anyway, but we'll assume infinite mass
+                itemVelocity *= _physicsQuery.TryComp(held, out var heldPhysics) ? heldPhysics.InvMass : 0;
+                // Throw at half the holder's intentional throw speed and
+                // vary the speed a little to make it look more interesting
+                var throwSpeed = entity.Comp.BaseThrowspeed * _random.NextFloat(0.45f, 0.55f);
+
                 _throwingSystem.TryThrow(held,
-                    _random.NextAngle().RotateVec(direction / dropAngle + worldRotation / 50),
-                    0.5f * dropAngle * _random.NextFloat(-0.9f, 1.1f),
-                    entity, 0);
+                    itemVelocity,
+                    throwSpeed,
+                    entity,
+                    pushbackRatio: 0,
+                    compensateFriction: false
+                );
             }
         }