Example #1
0
        /// <summary>
        ///     Knocks down the mob, making it fall to the ground.
        /// </summary>
        /// <param name="seconds">How many seconds the mob will stay on the ground</param>
        public void Knockdown(float seconds)
        {
            seconds = MathF.Min(_knockdownTimer + (seconds * KnockdownTimeModifier), _knockdownCap);

            if (seconds <= 0f)
            {
                return;
            }

            StandingStateHelper.Down(Owner);

            _knockdownTimer = seconds;
            _lastStun       = _gameTiming.CurTime;

            SetStatusEffect();
            Dirty();
        }
Example #2
0
        /// <summary>
        ///     Stuns the entity, disallowing it from doing many interactions temporarily.
        /// </summary>
        /// <param name="seconds">How many seconds the mob will stay stunned</param>
        public void Stun(float seconds)
        {
            seconds = MathF.Min(_stunnedTimer + (seconds * StunTimeModifier), _stunCap);

            if (seconds <= 0f)
            {
                return;
            }

            StandingStateHelper.DropAllItemsInHands(Owner, false);

            _stunnedTimer = seconds;
            _lastStun     = _gameTiming.CurTime;

            SetStatusEffect();
            Dirty();
        }
Example #3
0
        public void ExperiencePressureDifference(int cycle, float pressureDifference, Direction direction,
                                                 float pressureResistanceProbDelta, GridCoordinates throwTarget)
        {
            if (ControlledComponent == null)
            {
                return;
            }

            // TODO ATMOS stuns?

            var transform         = ControlledComponent.Owner.Transform;
            var pressureComponent = ControlledComponent.Owner.GetComponent <MovedByPressureComponent>();
            var maxForce          = MathF.Sqrt(pressureDifference) * 2.25f;
            var moveProb          = 100f;

            if (pressureComponent.PressureResistance > 0)
            {
                moveProb = MathF.Abs((pressureDifference / pressureComponent.PressureResistance * ProbabilityBasePercent) -
                                     ProbabilityOffset);
            }

            if (moveProb > ProbabilityOffset && _robustRandom.Prob(MathF.Min(moveProb / 100f, 1f)) &&
                !float.IsPositiveInfinity(pressureComponent.MoveResist) &&
                (!ControlledComponent.Anchored &&
                 (maxForce >= (pressureComponent.MoveResist * MoveForcePushRatio))) ||
                (ControlledComponent.Anchored && (maxForce >= (pressureComponent.MoveResist * MoveForceForcePushRatio))))
            {
                if (maxForce > ThrowForce && throwTarget != GridCoordinates.InvalidGrid)
                {
                    var moveForce = MathF.Min(maxForce * MathF.Clamp(moveProb, 0, 100) / 100f, 50f);
                    var pos       = throwTarget.Position - transform.GridPosition.Position;
                    LinearVelocity = pos * moveForce;
                }
                else
                {
                    var moveForce = MathF.Min(maxForce * MathF.Clamp(moveProb, 0, 100) / 100f, 25f);
                    LinearVelocity = direction.ToVec() * moveForce;
                }

                pressureComponent.LastHighPressureMovementAirCycle = cycle;
            }
        }
Example #4
0
        /// <summary>
        ///     Throw an entity at the position of <paramref name="targetLoc"/> from <paramref name="sourceLoc"/>,
        ///     without overshooting.
        /// </summary>
        /// <param name="thrownEnt">The entity to throw.</param>
        /// <param name="throwForceMax">
        /// The MAXIMUM force to throw the entity with.
        /// Throw force increases with distance to target, this is the maximum force allowed.
        /// </param>
        /// <param name="targetLoc">
        /// The target location to throw at.
        /// This function will try to land at this exact spot,
        /// if <paramref name="throwForceMax"/> is large enough to allow for it to be reached.
        /// </param>
        /// <param name="sourceLoc">
        /// The position to start the throw from.
        /// </param>
        /// <param name="spread">
        /// If true, slightly spread the actual throw angle.
        /// </param>
        /// <param name="throwSourceEnt">
        /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in.
        /// </param>
        public static void ThrowTo(IEntity thrownEnt, float throwForceMax, GridCoordinates targetLoc,
                                   GridCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null)
        {
            var mapManager = IoCManager.Resolve <IMapManager>();
            var timing     = IoCManager.Resolve <IGameTiming>();

            // Calculate the force necessary to land a throw based on throw duration, mass and distance.
            var distance      = (targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)).Length;
            var throwDuration = ThrownItemComponent.DefaultThrowTime;
            var mass          = 1f;

            if (thrownEnt.TryGetComponent(out IPhysicsComponent physicsComponent))
            {
                mass = physicsComponent.Mass;
            }

            var velocityNecessary = distance / throwDuration;
            var impulseNecessary  = velocityNecessary * mass;
            var forceNecessary    = impulseNecessary * (1f / timing.TickRate);

            // Then clamp it to the max force allowed and call Throw().
            Throw(thrownEnt, MathF.Min(forceNecessary, throwForceMax), targetLoc, sourceLoc, spread, throwSourceEnt);
        }
Example #5
0
        /// <summary>
        ///     Slows down the mob's walking/running speed temporarily
        /// </summary>
        /// <param name="seconds">How many seconds the mob will be slowed down</param>
        /// <param name="walkModifierOverride">Walk speed modifier. Set to 0 or negative for default value. (0.5f)</param>
        /// <param name="runModifierOverride">Run speed modifier. Set to 0 or negative for default value. (0.5f)</param>
        public void Slowdown(float seconds, float walkModifierOverride = 0f, float runModifierOverride = 0f)
        {
            seconds = MathF.Min(_slowdownTimer + (seconds * SlowdownTimeModifier), _slowdownCap);

            if (seconds <= 0f)
            {
                return;
            }

            WalkModifierOverride = walkModifierOverride;
            RunModifierOverride  = runModifierOverride;

            _slowdownTimer = seconds;
            _lastStun      = _gameTiming.CurTime;

            if (Owner.TryGetComponent(out MovementSpeedModifierComponent movement))
            {
                movement.RefreshMovementSpeedModifiers();
            }

            SetStatusEffect();
            Dirty();
        }
Example #6
0
 public static float Median(float a, float b, float c)
 {
     return(MathF.Max(MathF.Min(a, b), MathF.Min(MathF.Max(a, b), c)));
 }
Example #7
0
 public static float Min(float a, float b, float c, float d)
 {
     return(MathF.Min(a, MathF.Min(b, MathF.Min(c, d))));
 }
Example #8
0
        public bool Intersects(Box2 box, out float distance, out Vector2 hitPos)
        {
            hitPos   = Vector2.Zero;
            distance = 0;

            var         tmin    = 0.0f;           // set to -FLT_MAX to get first hit on line
            var         tmax    = float.MaxValue; // set to max distance ray can travel (for segment)
            const float epsilon = 1.0E-07f;

            // X axis slab
            {
                if (MathF.Abs(_direction.X) < epsilon)
                {
                    // ray is parallel to this slab, it will never hit unless ray is inside box
                    if (_position.X < MathF.Min(box.Left, box.Right) || _position.X > MathF.Max(box.Left, box.Right))
                    {
                        return(false);
                    }
                }

                // calculate intersection t value of ray with near and far plane of slab
                var ood = 1.0f / _direction.X;
                var t1  = (MathF.Min(box.Left, box.Right) - _position.X) * ood;
                var t2  = (MathF.Max(box.Left, box.Right) - _position.X) * ood;

                // Make t1 be the intersection with near plane, t2 with far plane
                if (t1 > t2)
                {
                    MathHelper.Swap(ref t1, ref t2);
                }

                // Compute the intersection of slab intersection intervals
                tmin = MathF.Max(t1, tmin);
                tmax = MathF.Min(t2, tmax); // Is this Min (SE) or Max(Textbook)

                // Exit with no collision as soon as slab intersection becomes empty
                if (tmin > tmax)
                {
                    return(false);
                }
            }

            // Y axis slab
            {
                if (MathF.Abs(_direction.Y) < epsilon)
                {
                    // ray is parallel to this slab, it will never hit unless ray is inside box
                    if (_position.Y < MathF.Min(box.Top, box.Bottom) || _position.Y > MathF.Max(box.Top, box.Bottom))
                    {
                        return(false);
                    }
                }

                // calculate intersection t value of ray with near and far plane of slab
                var ood = 1.0f / _direction.Y;
                var t1  = (MathF.Min(box.Top, box.Bottom) - _position.Y) * ood;
                var t2  = (MathF.Max(box.Top, box.Bottom) - _position.Y) * ood;

                // Make t1 be the intersection with near plane, t2 with far plane
                if (t1 > t2)
                {
                    MathHelper.Swap(ref t1, ref t2);
                }

                // Compute the intersection of slab intersection intervals
                tmin = MathF.Max(t1, tmin);
                tmax = MathF.Min(t2, tmax); // Is this Min (SE) or Max(Textbook)

                // Exit with no collision as soon as slab intersection becomes empty
                if (tmin > tmax)
                {
                    return(false);
                }
            }

            // Ray intersects all slabs. Return point and intersection t value
            hitPos   = _position + _direction * tmin;
            distance = tmin;
            return(true);
        }