/// <summary>
        ///     Set's the mob standing state to down.
        /// </summary>
        /// <param name="entity">The mob in question</param>
        /// <param name="playSound">Whether to play a sound when falling down or not</param>
        /// <param name="dropItems">Whether to make the mob drop all the items on his hands</param>
        /// <param name="force">Whether or not to check if the entity can fall.</param>
        /// <returns>False if the mob was already downed or couldn't set the state</returns>
        public static bool Down(IEntity entity, bool playSound = true, bool dropItems = true, bool force = false)
        {
            if (!force && !EffectBlockerSystem.CanFall(entity))
            {
                return(false);
            }

            if (!entity.TryGetComponent(out AppearanceComponent appearance))
            {
                return(false);
            }

            var newState = SharedSpeciesComponent.MobState.Down;

            appearance.TryGetData <SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var oldState);

            if (newState != oldState)
            {
                appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
            }

            if (playSound)
            {
                IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <AudioSystem>()
                .PlayFromEntity(AudioHelpers.GetRandomFileFromSoundCollection("bodyfall"), entity, AudioHelpers.WithVariation(0.25f));
            }

            if (dropItems)
            {
                DropAllItemsInHands(entity, false);
            }

            return(true);
        }
        bool IEffectBlocker.CanSlip()
        {
            if (Owner.TryGetComponent(out InventoryComponent inventoryComponent) &&
                inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent shoes)
                )
            {
                return(EffectBlockerSystem.CanSlip(shoes.Owner));
            }

            return(true);
        }
        public bool Down(IEntity entity, bool playSound = true, bool dropItems = true, bool force = false)
        {
            if (dropItems)
            {
                DropAllItemsInHands(entity, false);
            }

            if (!force && !EffectBlockerSystem.CanFall(entity))
            {
                return(false);
            }

            return(OnDown(entity, playSound, dropItems, force));
        }
示例#4
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);
        }
        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));
            }
        }
示例#6
0
        private bool TrySlip(SlipperyComponent component, IPhysBody ourBody, IPhysBody otherBody)
        {
            if (!component.Slippery ||
                component.Owner.IsInContainer() ||
                component.Slipped.Contains(otherBody.Owner.Uid) ||
                !otherBody.Owner.TryGetComponent(out SharedStunnableComponent? stun))
            {
                return(false);
            }

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

            var percentage = otherBody.GetWorldAABB().IntersectPercentage(ourBody.GetWorldAABB());

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

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

            otherBody.LinearVelocity *= component.LaunchForwardsMultiplier;

            stun.Paralyze(5);
            component.Slipped.Add(otherBody.Owner.Uid);
            component.Dirty();

            PlaySound(component);

            return(true);
        }
        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);
        }
        public async Task BuckleUnbuckleCooldownRangeTest()
        {
            var cOptions = new ClientIntegrationOptions {
                ExtraPrototypes = Prototypes
            };
            var sOptions = new ServerIntegrationOptions {
                ExtraPrototypes = Prototypes
            };

            var(_, server) = await StartConnectedServerClientPair(cOptions, sOptions);

            IEntity         human  = null;
            IEntity         chair  = null;
            BuckleComponent buckle = null;
            StrapComponent  strap  = null;

            await server.WaitAssertion(() =>
            {
                var mapManager    = IoCManager.Resolve <IMapManager>();
                var entityManager = IoCManager.Resolve <IEntityManager>();
                var actionBlocker = EntitySystem.Get <ActionBlockerSystem>();

                var gridId      = new GridId(1);
                var grid        = mapManager.GetGrid(gridId);
                var coordinates = grid.GridEntityId.ToCoordinates();

                human = entityManager.SpawnEntity(BuckleDummyId, coordinates);
                chair = entityManager.SpawnEntity(StrapDummyId, coordinates);

                // Default state, unbuckled
                Assert.True(human.TryGetComponent(out buckle));
                Assert.NotNull(buckle);
                Assert.Null(buckle.BuckledTo);
                Assert.False(buckle.Buckled);
                Assert.True(actionBlocker.CanMove(human));
                Assert.True(actionBlocker.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Default state, no buckled entities, strap
                Assert.True(chair.TryGetComponent(out strap));
                Assert.NotNull(strap);
                Assert.IsEmpty(strap.BuckledEntities);
                Assert.Zero(strap.OccupiedSize);

                // Side effects of buckling
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.NotNull(buckle.BuckledTo);
                Assert.True(buckle.Buckled);

                var player = IoCManager.Resolve <IPlayerManager>().GetAllPlayers().Single();
                Assert.True(((BuckleComponentState)buckle.GetComponentState(player)).Buckled);
                Assert.False(actionBlocker.CanMove(human));
                Assert.False(actionBlocker.CanChangeDirection(human));
                Assert.False(EffectBlockerSystem.CanFall(human));
                Assert.That(human.Transform.WorldPosition, Is.EqualTo(chair.Transform.WorldPosition));

                // Side effects of buckling for the strap
                Assert.That(strap.BuckledEntities, Does.Contain(human));
                Assert.That(strap.OccupiedSize, Is.EqualTo(buckle.Size));
                Assert.Positive(strap.OccupiedSize);

                // Trying to buckle while already buckled fails
                Assert.False(buckle.TryBuckle(human, chair));

                // Trying to unbuckle too quickly fails
                Assert.False(buckle.TryUnbuckle(human));
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
            });

            // Wait enough ticks for the unbuckling cooldown to run out
            await server.WaitRunTicks(60);

            await server.WaitAssertion(() =>
            {
                var actionBlocker = EntitySystem.Get <ActionBlockerSystem>();

                // Still buckled
                Assert.True(buckle.Buckled);

                // Unbuckle
                Assert.True(buckle.TryUnbuckle(human));
                Assert.Null(buckle.BuckledTo);
                Assert.False(buckle.Buckled);
                Assert.True(actionBlocker.CanMove(human));
                Assert.True(actionBlocker.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Unbuckle, strap
                Assert.IsEmpty(strap.BuckledEntities);
                Assert.Zero(strap.OccupiedSize);

                // Re-buckling has no cooldown
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.True(buckle.Buckled);

                // On cooldown
                Assert.False(buckle.TryUnbuckle(human));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
            });

            // Wait enough ticks for the unbuckling cooldown to run out
            await server.WaitRunTicks(60);

            await server.WaitAssertion(() =>
            {
                var actionBlocker = EntitySystem.Get <ActionBlockerSystem>();

                // Still buckled
                Assert.True(buckle.Buckled);

                // Unbuckle
                Assert.True(buckle.TryUnbuckle(human));
                Assert.False(buckle.Buckled);

                // Move away from the chair
                human.Transform.WorldPosition += (1000, 1000);

                // Out of range
                Assert.False(buckle.TryBuckle(human, chair));
                Assert.False(buckle.TryUnbuckle(human));
                Assert.False(buckle.ToggleBuckle(human, chair));

                // Move near the chair
                human.Transform.WorldPosition = chair.Transform.WorldPosition + (0.5f, 0);

                // In range
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.TryUnbuckle(human));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);

                // Force unbuckle
                Assert.True(buckle.TryUnbuckle(human, true));
                Assert.False(buckle.Buckled);
                Assert.True(actionBlocker.CanMove(human));
                Assert.True(actionBlocker.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Re-buckle
                Assert.True(buckle.TryBuckle(human, chair));

                // Move away from the chair
                human.Transform.WorldPosition += (1, 0);
            });

            await server.WaitRunTicks(1);

            await server.WaitAssertion(() =>
            {
                // No longer buckled
                Assert.False(buckle.Buckled);
                Assert.Null(buckle.BuckledTo);
                Assert.IsEmpty(strap.BuckledEntities);
            });
        }
示例#9
0
        public async Task BuckleUnbuckleCooldownRangeTest()
        {
            var server = StartServerDummyTicker();

            IEntity         human  = null;
            IEntity         chair  = null;
            BuckleComponent buckle = null;
            StrapComponent  strap  = null;

            await server.WaitAssertion(() =>
            {
                var mapManager = IoCManager.Resolve <IMapManager>();

                mapManager.CreateNewMapEntity(MapId.Nullspace);

                var entityManager = IoCManager.Resolve <IEntityManager>();

                human = entityManager.SpawnEntity("HumanMob_Content", MapCoordinates.Nullspace);
                chair = entityManager.SpawnEntity("ChairWood", MapCoordinates.Nullspace);

                // Default state, unbuckled
                Assert.True(human.TryGetComponent(out buckle));
                Assert.NotNull(buckle);
                Assert.Null(buckle.BuckledTo);
                Assert.False(buckle.Buckled);
                Assert.True(ActionBlockerSystem.CanMove(human));
                Assert.True(ActionBlockerSystem.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Default state, no buckled entities, strap
                Assert.True(chair.TryGetComponent(out strap));
                Assert.NotNull(strap);
                Assert.IsEmpty(strap.BuckledEntities);
                Assert.Zero(strap.OccupiedSize);

                // Side effects of buckling
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.NotNull(buckle.BuckledTo);
                Assert.True(buckle.Buckled);
                Assert.True(((BuckleComponentState)buckle.GetComponentState()).Buckled);
                Assert.False(ActionBlockerSystem.CanMove(human));
                Assert.False(ActionBlockerSystem.CanChangeDirection(human));
                Assert.False(EffectBlockerSystem.CanFall(human));
                Assert.That(human.Transform.WorldPosition, Is.EqualTo(chair.Transform.WorldPosition));

                // Side effects of buckling for the strap
                Assert.That(strap.BuckledEntities, Does.Contain(human));
                Assert.That(strap.OccupiedSize, Is.EqualTo(buckle.Size));
                Assert.Positive(strap.OccupiedSize);

                // Trying to buckle while already buckled fails
                Assert.False(buckle.TryBuckle(human, chair));

                // Trying to unbuckle too quickly fails
                Assert.False(buckle.TryUnbuckle(human));
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
            });

            // Wait enough ticks for the unbuckling cooldown to run out
            await server.WaitRunTicks(60);

            await server.WaitAssertion(() =>
            {
                // Still buckled
                Assert.True(buckle.Buckled);

                // Unbuckle
                Assert.True(buckle.TryUnbuckle(human));
                Assert.Null(buckle.BuckledTo);
                Assert.False(buckle.Buckled);
                Assert.True(ActionBlockerSystem.CanMove(human));
                Assert.True(ActionBlockerSystem.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Unbuckle, strap
                Assert.IsEmpty(strap.BuckledEntities);
                Assert.Zero(strap.OccupiedSize);

                // Re-buckling has no cooldown
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.True(buckle.Buckled);

                // On cooldown
                Assert.False(buckle.TryUnbuckle(human));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);
            });

            // Wait enough ticks for the unbuckling cooldown to run out
            await server.WaitRunTicks(60);

            await server.WaitAssertion(() =>
            {
                // Still buckled
                Assert.True(buckle.Buckled);

                // Unbuckle
                Assert.True(buckle.TryUnbuckle(human));
                Assert.False(buckle.Buckled);

                // Move away from the chair
                human.Transform.WorldPosition += (1000, 1000);

                // Out of range
                Assert.False(buckle.TryBuckle(human, chair));
                Assert.False(buckle.TryUnbuckle(human));
                Assert.False(buckle.ToggleBuckle(human, chair));

                // Move near the chair
                human.Transform.WorldPosition = chair.Transform.WorldPosition + (0.5f, 0);

                // In range
                Assert.True(buckle.TryBuckle(human, chair));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.TryUnbuckle(human));
                Assert.True(buckle.Buckled);
                Assert.False(buckle.ToggleBuckle(human, chair));
                Assert.True(buckle.Buckled);

                // Force unbuckle
                Assert.True(buckle.TryUnbuckle(human, true));
                Assert.False(buckle.Buckled);
                Assert.True(ActionBlockerSystem.CanMove(human));
                Assert.True(ActionBlockerSystem.CanChangeDirection(human));
                Assert.True(EffectBlockerSystem.CanFall(human));

                // Re-buckle
                Assert.True(buckle.TryBuckle(human, chair));

                // Move away from the chair
                human.Transform.WorldPosition += (1, 0);
            });

            await server.WaitRunTicks(1);

            await server.WaitAssertion(() =>
            {
                // No longer buckled
                Assert.False(buckle.Buckled);
                Assert.Null(buckle.BuckledTo);
                Assert.IsEmpty(strap.BuckledEntities);
            });
        }