Beispiel #1
0
        private static void UpdatePosition(IPhysBody body, float frameTime)
        {
            var ent = body.Entity;

            if (!body.CanMove() || (body.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(body.AngularVelocity) < Epsilon))
            {
                return;
            }

            if (body.LinearVelocity != Vector2.Zero)
            {
                var entityMoveMessage = new EntityMovementMessage();
                ent.SendMessage(ent.Transform, entityMoveMessage);

                if (ContainerHelpers.IsInContainer(ent))
                {
                    var relayEntityMoveMessage = new RelayMovementEntityMessage(ent);
                    ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage);
                    // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens.
                    body.LinearVelocity = Vector2.Zero;
                }
            }

            body.WorldRotation += body.AngularVelocity * frameTime;
            body.WorldPosition += body.LinearVelocity * frameTime;
        }
Beispiel #2
0
        private void UpdatePosition(ICollidableComponent collidable, float frameTime)
        {
            var ent = collidable.Entity;

            if (!collidable.CanMove() || (collidable.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(collidable.AngularVelocity) < Epsilon))
            {
                return;
            }

            if (collidable.LinearVelocity != Vector2.Zero)
            {
                if (ContainerHelpers.IsInContainer(ent))
                {
                    var relayEntityMoveMessage = new RelayMovementEntityMessage(ent);
                    ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage);
                    // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens.
                    collidable.LinearVelocity = Vector2.Zero;
                }
            }

            collidable.Owner.Transform.DeferUpdates = true;
            _deferredUpdates.Add(collidable);
            collidable.WorldRotation += collidable.AngularVelocity * frameTime;
            collidable.WorldPosition += collidable.LinearVelocity * frameTime;
        }
Beispiel #3
0
        private void UpdatePosition(IPhysicsComponent physics, float frameTime)
        {
            var ent = physics.Entity;

            if (!physics.CanMove() || (physics.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(physics.AngularVelocity) < Epsilon))
            {
                return;
            }

            if (physics.LinearVelocity != Vector2.Zero)
            {
                if (ContainerHelpers.IsInContainer(ent))
                {
                    var relayEntityMoveMessage = new RelayMovementEntityMessage(ent);
                    ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage);
                    // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens.
                    physics.LinearVelocity = Vector2.Zero;
                }
            }

            physics.Owner.Transform.DeferUpdates = true;
            _deferredUpdates.Add(physics);

            // Slow zone up in here
            if (physics.LinearVelocity.Length > _speedLimit)
            {
                physics.LinearVelocity = physics.LinearVelocity.Normalized * _speedLimit;
            }

            physics.WorldRotation += physics.AngularVelocity * frameTime;
            physics.WorldPosition += physics.LinearVelocity * frameTime;
        }
Beispiel #4
0
        private bool TrySliceFood(EntityUid uid, EntityUid user, EntityUid usedItem,
                                  SliceableFoodComponent?component = null, FoodComponent?food = null, TransformComponent?transform = null)
        {
            if (!Resolve(uid, ref component, ref food, ref transform) ||
                string.IsNullOrEmpty(component.Slice))
            {
                return(false);
            }

            if (!_solutionContainerSystem.TryGetSolution(uid, food.SolutionName, out var solution))
            {
                return(false);
            }

            if (!EntityManager.TryGetComponent(usedItem, out UtensilComponent ? utensil) || (utensil.Types & UtensilType.Knife) == 0)
            {
                return(false);
            }

            var sliceUid = EntityManager.SpawnEntity(component.Slice, transform.Coordinates);

            var lostSolution = _solutionContainerSystem.SplitSolution(uid, solution,
                                                                      solution.CurrentVolume / FixedPoint2.New(component.Count));

            // Fill new slice
            FillSlice(sliceUid, lostSolution);

            if (EntityManager.TryGetComponent(user, out HandsComponent? handsComponent))
            {
                if (ContainerHelpers.IsInContainer(component.Owner))
                {
                    handsComponent.PutInHandOrDrop(EntityManager.GetComponent <ItemComponent>(sliceUid));
                }
            }

            SoundSystem.Play(Filter.Pvs(uid), component.Sound.GetSound(), transform.Coordinates,
                             AudioParams.Default.WithVolume(-2));

            component.Count--;
            // If someone makes food proto with 1 slice...
            if (component.Count < 1)
            {
                EntityManager.DeleteEntity(uid);
                return(true);
            }

            // Split last slice
            if (component.Count == 1)
            {
                var lastSlice = EntityManager.SpawnEntity(component.Slice, transform.Coordinates);

                // Fill last slice with the rest of the solution
                FillSlice(lastSlice, solution);

                EntityManager.DeleteEntity(uid);
            }

            return(true);
        }
Beispiel #5
0
            protected override VerbVisibility GetVisibility(IEntity user, ItemComponent component)
            {
                if (ContainerHelpers.IsInContainer(component.Owner) || !component.CanPickup(user))
                {
                    return(VerbVisibility.Invisible);
                }

                return(VerbVisibility.Visible);
            }
            protected override void GetData(IEntity user, ItemComponent component, VerbData data)
            {
                if (ContainerHelpers.IsInContainer(component.Owner) || !component.CanPickup(user))
                {
                    data.Visibility = VerbVisibility.Invisible;
                    return;
                }

                data.Text = "Pick Up";
            }
        private void UpdatePosition(IPhysicsComponent physics, float frameTime)
        {
            var ent = physics.Entity;

            if (!physics.CanMove() || (physics.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(physics.AngularVelocity) < Epsilon))
            {
                return;
            }

            if (physics.LinearVelocity != Vector2.Zero)
            {
                if (ContainerHelpers.IsInContainer(ent))
                {
                    var relayEntityMoveMessage = new RelayMovementEntityMessage(ent);
                    ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage);
                    // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens.
                    physics.LinearVelocity = Vector2.Zero;
                }
            }

            physics.Owner.Transform.DeferUpdates = true;
            _deferredUpdates.Add(physics);

            // Slow zone up in here
            if (physics.LinearVelocity.Length > _speedLimit)
            {
                physics.LinearVelocity = physics.LinearVelocity.Normalized * _speedLimit;
            }

            var newPosition = physics.WorldPosition + physics.LinearVelocity * frameTime;
            var owner       = physics.Owner;
            var transform   = owner.Transform;

            // Change parent if necessary
            if (!ContainerHelpers.IsInContainer(owner))
            {
                // This shoouullddnnn'''tt de-parent anything in a container because none of that should have physics applied to it.
                if (_mapManager.TryFindGridAt(owner.Transform.MapID, newPosition, out var grid) &&
                    grid.GridEntityId.IsValid() &&
                    grid.GridEntityId != owner.Uid)
                {
                    if (grid.GridEntityId != transform.ParentUid)
                    {
                        transform.AttachParent(owner.EntityManager.GetEntity(grid.GridEntityId));
                    }
                }
                else
                {
                    transform.AttachParent(_mapManager.GetMapEntity(transform.MapID));
                }
            }

            physics.WorldRotation += physics.AngularVelocity * frameTime;
            physics.WorldPosition  = newPosition;
        }
Beispiel #8
0
            protected override void GetData(IEntity user, ItemComponent component, VerbData data)
            {
                if (!ActionBlockerSystem.CanInteract(user) ||
                    ContainerHelpers.IsInContainer(component.Owner) ||
                    !component.CanPickup(user))
                {
                    data.Visibility = VerbVisibility.Invisible;
                    return;
                }

                data.Text = Loc.GetString("Pick Up");
            }
        async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
        {
            if (string.IsNullOrEmpty(_slice))
            {
                return(false);
            }

            var scs = EntitySystem.Get <SolutionContainerSystem>();

            if (!Owner.TryGetComponent <FoodComponent>(out var foodComp) || !scs.TryGetSolution(Owner, foodComp.SolutionName, out var solution))
            {
                return(false);
            }

            if (!eventArgs.Using.TryGetComponent(out UtensilComponent? utensil) || !utensil.HasType(UtensilType.Knife))
            {
                return(false);
            }

            var itemToSpawn = Owner.EntityManager.SpawnEntity(_slice, Owner.Transform.Coordinates);
            // This is done this way so that... food additives (read: poisons) remain in the system.
            // Basically, we want to:
            // 1. Split off a representative chunk
            var lostSolution = scs.SplitSolution(Owner.Uid, solution,
                                                 solution.CurrentVolume / ReagentUnit.New(Count));

            // 2. Delete the Nutriment (it's already in the target) so we just have additives
            // It might be an idea to remove the removal of Nutriment & clear the food
            lostSolution.RemoveReagent("Nutriment", lostSolution.GetReagentQuantity("Nutriment"));
            // 3. Dump whatever we can into the slice
            if (itemToSpawn.TryGetComponent <FoodComponent>(out var itsFoodComp) && scs.TryGetSolution(itemToSpawn, itsFoodComp.SolutionName, out var itsSolution))
            {
                var lostSolutionPart = lostSolution.SplitSolution(itsSolution.AvailableVolume);
                scs.TryAddSolution(itemToSpawn.Uid, itsSolution, lostSolutionPart);
            }
            if (eventArgs.User.TryGetComponent(out HandsComponent? handsComponent))
            {
                if (ContainerHelpers.IsInContainer(Owner))
                {
                    handsComponent.PutInHandOrDrop(itemToSpawn.GetComponent <ItemComponent>());
                }
            }

            SoundSystem.Play(Filter.Pvs(Owner), _sound.GetSound(), Owner.Transform.Coordinates,
                             AudioParams.Default.WithVolume(-2));

            Count--;
            if (Count < 1)
            {
                Owner.Delete();
            }
            return(true);
        }
Beispiel #10
0
        //[MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void HighPressureMovements()
        {
            // TODO ATMOS finish this

            if (PressureDifference > 15)
            {
                if (_soundCooldown == 0)
                {
                    EntitySystem.Get <AudioSystem>().PlayAtCoords("/Audio/Effects/space_wind.ogg",
                                                                  GridIndices.ToGridCoordinates(_mapManager, GridIndex), AudioHelpers.WithVariation(0.125f).WithVolume(MathHelper.Clamp(PressureDifference / 10, 10, 100)));
                }
            }


            foreach (var entity in _entityManager.GetEntitiesIntersecting(_mapManager.GetGrid(GridIndex).ParentMapId, Box2.UnitCentered.Translated(GridIndices)))
            {
                if (!entity.TryGetComponent(out ICollidableComponent physics) ||
                    !entity.TryGetComponent(out MovedByPressureComponent pressure) ||
                    ContainerHelpers.IsInContainer(entity))
                {
                    continue;
                }

                physics.WakeBody();

                var pressureMovements = physics.EnsureController <HighPressureMovementController>();
                if (pressure.LastHighPressureMovementAirCycle < _gridAtmosphereComponent.UpdateCounter)
                {
                    pressureMovements.ExperiencePressureDifference(_gridAtmosphereComponent.UpdateCounter, PressureDifference, _pressureDirection, 0, PressureSpecificTarget?.GridIndices.ToGridCoordinates(_mapManager, GridIndex) ?? GridCoordinates.InvalidGrid);
                }
            }

            if (PressureDifference > 100)
            {
                // Do space wind graphics here!
            }

            _soundCooldown++;
            if (_soundCooldown > 75)
            {
                _soundCooldown = 0;
            }
        }
Beispiel #11
0
        private bool TrySlip(IEntity entity)
        {
            if (!Slippery ||
                ContainerHelpers.IsInContainer(Owner) ||
                _slipped.Contains(entity.Uid) ||
                !entity.TryGetComponent(out SharedStunnableComponent stun) ||
                !entity.TryGetComponent(out ICollidableComponent otherBody) ||
                !Owner.TryGetComponent(out ICollidableComponent body))
            {
                return(false);
            }

            if (otherBody.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
            {
                return(false);
            }

            var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);

            if (percentage < IntersectPercentage)
            {
                return(false);
            }

            if (!EffectBlockerSystem.CanSlip(entity))
            {
                return(false);
            }

            if (entity.TryGetComponent(out ICollidableComponent collidable))
            {
                var controller = collidable.EnsureController <SlipController>();
                controller.LinearVelocity = collidable.LinearVelocity * LaunchForwardsMultiplier;
            }

            stun.Paralyze(5);
            _slipped.Add(entity.Uid);

            OnSlip();

            return(true);
        }
        // TODO: When I spawn new entities they seem to duplicate clothing or something?
        public override Outcome Execute(float frameTime)
        {
            if (_target == null ||
                _target.Deleted ||
                !_target.HasComponent <ItemComponent>() ||
                ContainerHelpers.IsInContainer(_target) ||
                !InteractionChecks.InRangeUnobstructed(_owner, _target.Transform.MapPosition))
            {
                return(Outcome.Failed);
            }

            if (!_owner.TryGetComponent(out HandsComponent handsComponent))
            {
                return(Outcome.Failed);
            }

            var emptyHands = false;

            foreach (var hand in handsComponent.ActivePriorityEnumerable())
            {
                if (handsComponent.GetItem(hand) == null)
                {
                    if (handsComponent.ActiveHand != hand)
                    {
                        handsComponent.ActiveHand = hand;
                    }

                    emptyHands = true;
                    break;
                }
            }

            if (!emptyHands)
            {
                return(Outcome.Failed);
            }

            var interactionSystem = IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <InteractionSystem>();

            interactionSystem.Interaction(_owner, _target);
            return(Outcome.Success);
        }
Beispiel #13
0
        async Task <bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
        {
            if (string.IsNullOrEmpty(_slice))
            {
                return(false);
            }

            if (!EntitySystem.Get <SolutionContainerSystem>().TryGetSolution(Owner, FoodComponent.SolutionName, out var solution))
            {
                return(false);
            }

            if (!eventArgs.Using.TryGetComponent(out UtensilComponent? utensil) || !utensil.HasType(UtensilType.Knife))
            {
                return(false);
            }

            var itemToSpawn = Owner.EntityManager.SpawnEntity(_slice, Owner.Transform.Coordinates);

            if (eventArgs.User.TryGetComponent(out HandsComponent? handsComponent))
            {
                if (ContainerHelpers.IsInContainer(Owner))
                {
                    handsComponent.PutInHandOrDrop(itemToSpawn.GetComponent <ItemComponent>());
                }
            }

            SoundSystem.Play(Filter.Pvs(Owner), _sound.GetSound(), Owner.Transform.Coordinates,
                             AudioParams.Default.WithVolume(-2));

            Count--;
            if (Count < 1)
            {
                Owner.Delete();
                return(true);
            }

            EntitySystem.Get <SolutionContainerSystem>().TryRemoveReagent(Owner.Uid, solution, "Nutriment",
                                                                          solution.CurrentVolume / ReagentUnit.New(Count + 1));
            return(true);
        }
        public void CollideWith(IEntity collidedWith)
        {
            if (ContainerHelpers.IsInContainer(Owner) ||
                _slipped.Contains(collidedWith.Uid) ||
                !collidedWith.TryGetComponent(out StunnableComponent stun) ||
                !collidedWith.TryGetComponent(out ICollidableComponent otherBody) ||
                !collidedWith.TryGetComponent(out IPhysicsComponent otherPhysics) ||
                !Owner.TryGetComponent(out ICollidableComponent body))
            {
                return;
            }

            if (otherPhysics.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
            {
                return;
            }

            var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);

            if (percentage < IntersectPercentage)
            {
                return;
            }

            if (!EffectBlockerSystem.CanSlip(collidedWith))
            {
                return;
            }

            stun.Paralyze(5f);
            _slipped.Add(collidedWith.Uid);

            if (!string.IsNullOrEmpty(SlipSound))
            {
                EntitySystem.Get <AudioSystem>().PlayFromEntity(SlipSound, Owner, AudioHelpers.WithVariation(0.2f));
            }
        }
        private bool TrySlip(IEntity entity)
        {
            if (ContainerHelpers.IsInContainer(Owner) ||
                _slipped.Contains(entity.Uid) ||
                !entity.TryGetComponent(out SharedStunnableComponent stun) ||
                !entity.TryGetComponent(out ICollidableComponent otherBody) ||
                !entity.TryGetComponent(out IPhysicsComponent otherPhysics) ||
                !Owner.TryGetComponent(out ICollidableComponent body))
            {
                return(false);
            }

            if (otherPhysics.LinearVelocity.Length < RequiredSlipSpeed || stun.KnockedDown)
            {
                return(false);
            }

            var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB);

            if (percentage < IntersectPercentage)
            {
                return(false);
            }

            if (!EffectBlockerSystem.CanSlip(entity))
            {
                return(false);
            }

            stun.Paralyze(5);
            _slipped.Add(entity.Uid);

            OnSlip();

            return(true);
        }
Beispiel #16
0
        private void HandleMovement(IEntity entity, float frameTime)
        {
            if (entity.Deleted)
            {
                // Ugh let's hope this fixes the crashes.
                return;
            }

            var velocity = entity.GetComponent <PhysicsComponent>();

            if (velocity.DidMovementCalculations)
            {
                velocity.DidMovementCalculations = false;
                return;
            }

            if (velocity.AngularVelocity == 0 && velocity.LinearVelocity == Vector2.Zero)
            {
                return;
            }

            var transform = entity.Transform;

            if (ContainerHelpers.IsInContainer(transform.Owner))
            {
                transform.Parent.Owner.SendMessage(transform, new RelayMovementEntityMessage(entity));
                velocity.LinearVelocity = Vector2.Zero;
                return;
            }

            var     velocityConsumers = velocity.GetVelocityConsumers();
            var     initialMovement   = velocity.LinearVelocity;
            int     velocityConsumerCount;
            float   totalMass;
            Vector2 lowestMovement;

            do
            {
                velocityConsumerCount = velocityConsumers.Count;
                totalMass             = 0;
                lowestMovement        = initialMovement;
                var copy = new List <Vector2>(velocityConsumers.Count);
                foreach (var consumer in velocityConsumers)
                {
                    totalMass += consumer.Mass;
                    var movement = lowestMovement * velocity.Mass / totalMass;
                    consumer.AngularVelocity = velocity.AngularVelocity;
                    consumer.LinearVelocity  = movement;
                    copy.Add(CalculateMovement(consumer, frameTime, consumer.Owner) / frameTime);
                }

                copy.Sort(LengthComparer);
                lowestMovement    = copy[0];
                velocityConsumers = velocity.GetVelocityConsumers();
            } while (velocityConsumers.Count != velocityConsumerCount);

            velocity.ClearVelocityConsumers();

            foreach (var consumer in velocityConsumers)
            {
                consumer.LinearVelocity          = lowestMovement;
                consumer.DidMovementCalculations = true;
            }

            velocity.DidMovementCalculations = false;
        }
Beispiel #17
0
        private static void HandleMovement(IMapManager mapManager, ITileDefinitionManager tileDefinitionManager, IEntity entity, float frameTime)
        {
            if (entity.Deleted)
            {
                // Ugh let's hope this fixes the crashes.
                return;
            }

            var velocity = entity.GetComponent <PhysicsComponent>();

            if (velocity.DidMovementCalculations)
            {
                velocity.DidMovementCalculations = false;
                return;
            }

            if (velocity.AngularVelocity == 0 && velocity.LinearVelocity == Vector2.Zero)
            {
                return;
            }

            var transform = entity.Transform;

            if (ContainerHelpers.IsInContainer(transform.Owner))
            {
                transform.Parent.Owner.SendMessage(transform, new RelayMovementEntityMessage(entity));
                velocity.LinearVelocity = Vector2.Zero;
                return;
            }

            var     velocityConsumers = velocity.GetVelocityConsumers();
            var     initialMovement   = velocity.LinearVelocity;
            int     velocityConsumerCount;
            float   totalMass;
            Vector2 lowestMovement;
            var     tile =
                mapManager.GetGrid(entity.Transform.GridID).GetTileRef(entity.Transform.GridPosition).Tile;
            bool hasGravity = mapManager.GetGrid(entity.Transform.GridID).HasGravity&& !tile.IsEmpty;

            do
            {
                velocityConsumerCount = velocityConsumers.Count;
                totalMass             = 0;
                lowestMovement        = initialMovement;
                var   copy          = new List <Vector2>(velocityConsumers.Count);
                float totalFriction = 0;
                foreach (var consumer in velocityConsumers)
                {
                    var movement = lowestMovement;
                    totalMass += consumer.Mass;
                    if (hasGravity)
                    {
                        totalFriction += GetFriction(tileDefinitionManager, mapManager, consumer.Owner);
                        movement      *= velocity.Mass / (totalMass != 0 ? totalMass + (totalMass * totalFriction) : 1);
                    }
                    consumer.AngularVelocity = velocity.AngularVelocity;
                    consumer.LinearVelocity  = movement;
                    copy.Add(CalculateMovement(tileDefinitionManager, mapManager, consumer, frameTime, consumer.Owner) / frameTime);
                }

                copy.Sort(LengthComparer);
                lowestMovement    = copy[0];
                velocityConsumers = velocity.GetVelocityConsumers();
            } while (velocityConsumers.Count != velocityConsumerCount);

            velocity.ClearVelocityConsumers();

            foreach (var consumer in velocityConsumers)
            {
                consumer.LinearVelocity          = lowestMovement;
                consumer.DidMovementCalculations = true;
            }

            velocity.DidMovementCalculations = false;
        }