Exemplo n.º 1
0
        /// <summary>
        ///     Tries to throw the entity if it has a physics component, otherwise does nothing.
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="direction">Will use the vector's magnitude as the strength of the impulse</param>
        /// <param name="user"></param>
        /// <param name="pushbackRatio">The ratio of impulse applied to the thrower</param>
        internal static void TryThrow(this IEntity entity, Vector2 direction, IEntity?user = null, float pushbackRatio = 1.0f)
        {
            if (entity.Deleted || direction == Vector2.Zero || !entity.TryGetComponent(out PhysicsComponent? physicsComponent))
            {
                return;
            }

            if (physicsComponent.BodyType == BodyType.Static)
            {
                Logger.Warning("Tried to throw entity {entity} but can't throw static bodies!");
                return;
            }

            if (entity.HasComponent <IMobStateComponent>())
            {
                Logger.Warning("Throwing not supported for mobs!");
                return;
            }

            if (entity.HasComponent <ItemComponent>())
            {
                entity.EnsureComponent <ThrownItemComponent>().Thrower = user;
                // Give it a l'il spin.
                if (!entity.HasTag("NoSpinOnThrow"))
                {
                    physicsComponent.ApplyAngularImpulse(ThrowAngularImpulse);
                }
                else
                {
                    entity.Transform.LocalRotation = direction.ToWorldAngle() - Math.PI;
                }

                if (user != null)
                {
                    EntitySystem.Get <InteractionSystem>().ThrownInteraction(user, entity);
                }
            }

            physicsComponent.ApplyLinearImpulse(direction);
            // Give thrower an impulse in the other direction
            if (user != null && pushbackRatio > 0.0f && user.TryGetComponent(out IPhysBody? body))
            {
                var msg = new ThrowPushbackAttemptEvent();
                body.Owner.EntityManager.EventBus.RaiseLocalEvent(body.Owner.Uid, msg);

                if (!msg.Cancelled)
                {
                    body.ApplyLinearImpulse(-direction * pushbackRatio);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Tries to throw the entity if it has a physics component, otherwise does nothing.
        /// </summary>
        /// <param name="entity">The entity being thrown.</param>
        /// <param name="direction">A vector pointing from the entity to its destination.</param>
        /// <param name="strength">How much the direction vector should be multiplied for velocity.</param>
        /// <param name="user"></param>
        /// <param name="pushbackRatio">The ratio of impulse applied to the thrower</param>
        internal static void TryThrow(this IEntity entity, Vector2 direction, float strength = 1.0f, IEntity?user = null, float pushbackRatio = 1.0f)
        {
            if (entity.Deleted ||
                direction == Vector2.Zero ||
                strength <= 0f ||
                !entity.TryGetComponent(out PhysicsComponent? physicsComponent))
            {
                return;
            }

            if (physicsComponent.BodyType == BodyType.Static)
            {
                Logger.Warning("Tried to throw entity {entity} but can't throw static bodies!");
                return;
            }

            if (entity.HasComponent <IMobStateComponent>())
            {
                Logger.Warning("Throwing not supported for mobs!");
                return;
            }

            if (entity.HasComponent <ItemComponent>())
            {
                entity.EnsureComponent <ThrownItemComponent>().Thrower = user;
                // Give it a l'il spin.
                if (!entity.HasTag("NoSpinOnThrow"))
                {
                    physicsComponent.ApplyAngularImpulse(ThrowAngularImpulse);
                }
                else
                {
                    entity.Transform.LocalRotation = direction.ToWorldAngle() - Math.PI;
                }

                if (user != null)
                {
                    EntitySystem.Get <InteractionSystem>().ThrownInteraction(user, entity);
                }
            }

            var impulseVector = direction.Normalized * strength * physicsComponent.Mass;

            physicsComponent.ApplyLinearImpulse(impulseVector);

            // Estimate time to arrival so we can apply OnGround status and slow it much faster.
            var time = (direction / strength).Length;

            if (time < FlyTime)
            {
                physicsComponent.BodyStatus = BodyStatus.OnGround;
            }
            else
            {
                physicsComponent.BodyStatus = BodyStatus.InAir;

                Timer.Spawn(TimeSpan.FromSeconds(time - FlyTime), () =>
                {
                    if (physicsComponent.Deleted)
                    {
                        return;
                    }
                    physicsComponent.BodyStatus = BodyStatus.OnGround;
                });
            }

            // Give thrower an impulse in the other direction
            if (user != null && pushbackRatio > 0.0f && user.TryGetComponent(out IPhysBody? body))
            {
                var msg = new ThrowPushbackAttemptEvent();
                body.Owner.EntityManager.EventBus.RaiseLocalEvent(body.Owner.Uid, msg);

                if (!msg.Cancelled)
                {
                    body.ApplyLinearImpulse(-impulseVector * pushbackRatio);
                }
            }
        }
Exemplo n.º 3
0
 private void HandleThrowPushback(EntityUid uid, SharedBuckleComponent component, ThrowPushbackAttemptEvent args)
 {
     if (!component.Buckled)
     {
         return;
     }
     args.Cancel();
 }
Exemplo n.º 4
0
    /// <summary>
    ///     Tries to throw the entity if it has a physics component, otherwise does nothing.
    /// </summary>
    /// <param name="entity">The entity being thrown.</param>
    /// <param name="direction">A vector pointing from the entity to its destination.</param>
    /// <param name="strength">How much the direction vector should be multiplied for velocity.</param>
    /// <param name="user"></param>
    /// <param name="pushbackRatio">The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced</param>
    public void TryThrow(
        EntityUid uid,
        Vector2 direction,
        float strength               = 1.0f,
        EntityUid?user               = null,
        float pushbackRatio          = 10.0f,
        PhysicsComponent?physics     = null,
        TransformComponent?transform = null,
        EntityQuery <PhysicsComponent>?physicsQuery = null,
        EntityQuery <TransformComponent>?xformQuery = null)
    {
        if (strength <= 0 || direction == Vector2.Infinity || direction == Vector2.NaN || direction == Vector2.Zero)
        {
            return;
        }

        physicsQuery ??= GetEntityQuery <PhysicsComponent>();
        if (physics == null && !physicsQuery.Value.TryGetComponent(uid, out physics))
        {
            return;
        }

        if (physics.BodyType != BodyType.Dynamic)
        {
            Logger.Warning($"Tried to throw entity {ToPrettyString(uid)} but can't throw {physics.BodyType} bodies!");
            return;
        }

        var comp = EnsureComp <ThrownItemComponent>(uid);

        comp.Thrower = user;
        // Give it a l'il spin.
        if (!_tagSystem.HasTag(uid, "NoSpinOnThrow"))
        {
            physics.ApplyAngularImpulse(ThrowAngularImpulse);
        }
        else
        {
            if (transform == null)
            {
                xformQuery ??= GetEntityQuery <TransformComponent>();
                transform = xformQuery.Value.GetComponent(uid);
            }
            transform.LocalRotation = direction.ToWorldAngle() - Math.PI;
        }

        if (user != null)
        {
            _interactionSystem.ThrownInteraction(user.Value, uid);
        }

        var impulseVector = direction.Normalized * strength * physics.Mass;

        physics.ApplyLinearImpulse(impulseVector);

        // Estimate time to arrival so we can apply OnGround status and slow it much faster.
        var time = (direction / strength).Length;

        if (time < FlyTime)
        {
            physics.BodyStatus = BodyStatus.OnGround;
            _thrownSystem.LandComponent(comp);
        }
        else
        {
            physics.BodyStatus = BodyStatus.InAir;

            Timer.Spawn(TimeSpan.FromSeconds(time - FlyTime), () =>
            {
                if (physics.Deleted)
                {
                    return;
                }
                physics.BodyStatus = BodyStatus.OnGround;
                _thrownSystem.LandComponent(comp);
            });
        }

        // Give thrower an impulse in the other direction
        if (user != null && pushbackRatio > 0.0f && physicsQuery.Value.TryGetComponent(user.Value, out var userPhysics))
        {
            var msg = new ThrowPushbackAttemptEvent();
            RaiseLocalEvent(physics.Owner, msg, false);

            if (!msg.Cancelled)
            {
                userPhysics.ApplyLinearImpulse(-impulseVector * pushbackRatio);
            }
        }
    }
Exemplo n.º 5
0
        /// <summary>
        ///     Tries to throw the entity if it has a physics component, otherwise does nothing.
        /// </summary>
        /// <param name="entity">The entity being thrown.</param>
        /// <param name="direction">A vector pointing from the entity to its destination.</param>
        /// <param name="strength">How much the direction vector should be multiplied for velocity.</param>
        /// <param name="user"></param>
        /// <param name="pushbackRatio">The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced</param>
        internal static void TryThrow(this EntityUid entity, Vector2 direction, float strength = 1.0f, EntityUid?user = null, float pushbackRatio = 10.0f)
        {
            var entities = IoCManager.Resolve <IEntityManager>();

            if (entities.GetComponent <MetaDataComponent>(entity).EntityDeleted ||
                strength <= 0f ||
                !entities.TryGetComponent(entity, out PhysicsComponent? physicsComponent))
            {
                return;
            }

            if (physicsComponent.BodyType != BodyType.Dynamic)
            {
                Logger.Warning($"Tried to throw entity {entities.ToPrettyString(entity)} but can't throw {physicsComponent.BodyType} bodies!");
                return;
            }

            var comp = entity.EnsureComponent <ThrownItemComponent>();

            if (entities.HasComponent <SharedItemComponent>(entity))
            {
                comp.Thrower = user;
                // Give it a l'il spin.
                if (!EntitySystem.Get <TagSystem>().HasTag(entity, "NoSpinOnThrow"))
                {
                    physicsComponent.ApplyAngularImpulse(ThrowAngularImpulse);
                }
                else if (direction != Vector2.Zero)
                {
                    entities.GetComponent <TransformComponent>(entity).LocalRotation = direction.ToWorldAngle() - Math.PI;
                }

                if (user != null)
                {
                    EntitySystem.Get <InteractionSystem>().ThrownInteraction(user.Value, entity);
                }
            }

            var impulseVector = direction.Normalized * strength * physicsComponent.Mass;

            physicsComponent.ApplyLinearImpulse(impulseVector);

            // Estimate time to arrival so we can apply OnGround status and slow it much faster.
            var time = (direction / strength).Length;

            if (time < FlyTime)
            {
                physicsComponent.BodyStatus = BodyStatus.OnGround;
                EntitySystem.Get <ThrownItemSystem>().LandComponent(comp);
            }
            else
            {
                physicsComponent.BodyStatus = BodyStatus.InAir;

                Timer.Spawn(TimeSpan.FromSeconds(time - FlyTime), () =>
                {
                    if (physicsComponent.Deleted)
                    {
                        return;
                    }
                    physicsComponent.BodyStatus = BodyStatus.OnGround;
                    EntitySystem.Get <ThrownItemSystem>().LandComponent(comp);
                });
            }

            // Give thrower an impulse in the other direction
            if (user != null && pushbackRatio > 0.0f && entities.TryGetComponent(user.Value, out IPhysBody? body))
            {
                var msg = new ThrowPushbackAttemptEvent();
                entities.EventBus.RaiseLocalEvent(body.Owner, msg);

                if (!msg.Cancelled)
                {
                    body.ApplyLinearImpulse(-impulseVector * pushbackRatio);
                }
            }
        }