[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();
CommandBinds.Builder
.Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem))
.Register<HandsSystem>();
+
+ _physicsQuery = GetEntityQuery<PhysicsComponent>();
}
public override void Shutdown()
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)
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
+ );
}
}