예제 #1
0
        /// <summary>
        ///
        /// </summary>
        private void CalculateMovementVelocity()
        {
            switch (_surfer.MoveType)
            {
            case MoveType.Walk:
                if (_surfer.GroundObject == null)
                {
                    // apply movement from input
                    _surfer.MoveData.Velocity += AirInputMovement();

                    // let the magic happen
                    SurfPhysics.Reflect(ref _surfer.MoveData.Velocity, _surfer.Collider, _surfer.MoveData.Origin, _deltaTime);
                }
                else
                {
                    // apply movement from input
                    _surfer.MoveData.Velocity += GroundInputMovement();

                    // jump/friction
                    if (_surfer.MoveData.Buttons.HasFlag((int)InputButtons.Jump))
                    {
                        Jump();
                    }
                    else
                    {
                        var friction  = _surfer.MoveData.SurfaceFriction * _config.Friction;
                        var stopSpeed = _config.StopSpeed;
                        SurfPhysics.Friction(ref _surfer.MoveData.Velocity, stopSpeed, friction, _deltaTime);
                    }
                }

                break;
            }
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            if (!_surfer.moveData.underwater)
            {
                if (_surfer.moveData.velocity.y <= 0f)
                {
                    jumping = false;
                }

                // apply gravity
                if (_surfer.groundObject == null)
                {
                    _surfer.moveData.velocity.y -= (_surfer.moveData.gravityFactor * _config.gravity * _deltaTime);
                    _surfer.moveData.velocity.y += _surfer.baseVelocity.y * _deltaTime;
                }

                // input velocity, check for ground
                CheckGrounded();
                CalculateMovementVelocity();
            }
            else
            {
                // Do underwater logic
                UnderwaterPhysics();
            }

            float yVel = _surfer.moveData.velocity.y;

            _surfer.moveData.velocity.y = 0f;
            _surfer.moveData.velocity   = Vector3.ClampMagnitude(_surfer.moveData.velocity, _config.maxVelocity);
            speed = _surfer.moveData.velocity.magnitude;
            _surfer.moveData.velocity.y = yVel;

            float   maxDistPerFrame   = 1f;
            Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime;
            float   velocityDistLeft  = velocityThisFrame.magnitude;
            float   initialVel        = velocityDistLeft;

            while (velocityDistLeft > 0f)
            {
                float amountThisLoop = Mathf.Min(maxDistPerFrame, velocityDistLeft);
                velocityDistLeft -= amountThisLoop;

                // increment origin
                Vector3 velThisLoop = velocityThisFrame * (amountThisLoop / initialVel);
                _surfer.moveData.origin += velThisLoop;

                // don't penetrate walls
                SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce);
            }

            _surfer.moveData.groundedTemp = _surfer.moveData.grounded;

            _surfer = null;
        }
예제 #3
0
        ///// Methods /////

        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            // apply gravity
            if (_surfer.GroundObject == null)
            {
                _surfer.MoveData.Velocity.y -= (_surfer.MoveData.GravityFactor * _config.Gravity * _deltaTime);
                _surfer.MoveData.Velocity.y += _surfer.BaseVelocity.y * _deltaTime;
            }

            // input velocity, check for ground
            CheckGrounded();
            CalculateMovementVelocity();

            // increment origin
            _surfer.MoveData.Origin += _surfer.MoveData.Velocity * _deltaTime;

            // don't penetrate walls
            SurfPhysics.ResolveCollisions(_surfer.Collider, ref _surfer.MoveData.Origin, ref _surfer.MoveData.Velocity);

            _surfer = null;
        }
예제 #4
0
        private void CheckSlope()
        {
            if (_surfer.MoveData.Surfing)
            {
                return;
            }

            var origin    = _surfer.MoveData.Origin + new Vector3(0, _surfer.Collider.bounds.extents.y + 0.1f, 0);
            var direction = Vector3.down;
            var distance  = 0.2f;

            var hitCount = Physics.BoxCastNonAlloc(results: _hitCache,
                                                   center: origin,
                                                   direction: direction,
                                                   orientation: Quaternion.identity,
                                                   maxDistance: distance,
                                                   halfExtents: _surfer.Collider.bounds.extents,
                                                   layerMask: SurfPhysics.GroundLayerMask,
                                                   queryTriggerInteraction: QueryTriggerInteraction.Ignore);

            for (int i = 0; i < hitCount; i++)
            {
                if (_hitCache[i].normal.y <= SurfPhysics.SurfSlope)
                {
                    continue;
                }

                if (_hitCache[i].normal.y >= 1)
                {
                    continue;
                }

                var slopeDir          = Vector3.Cross(Vector3.up, Vector3.Cross(Vector3.up, _hitCache[i].normal));
                var dot               = Vector3.Dot(_surfer.MoveData.AbsVelocity.normalized, slopeDir);
                var goingAgainstSlope = dot > 0;

                if (!goingAgainstSlope)
                {
                    continue;
                }

                Debug.DrawLine(origin, _hitCache[i].point, Color.magenta, 5f);

                _surfer.MoveData.MomentumModifier = _hitCache[i].normal;
                SurfPhysics.ClipVelocity(_surfer.MoveData.Velocity, _hitCache[i].normal, ref _surfer.MoveData.Velocity, 1.0f);
                SurfPhysics.ClipVelocity(_surfer.MoveData.BaseVelocity, _hitCache[i].normal, ref _surfer.MoveData.BaseVelocity, 1.0f);

                var end = origin + _surfer.MoveData.AbsVelocity.normalized * 2f;

                Debug.DrawLine(origin, end, Color.red, 5f);
            }

            //// todo: remove reflect function, seems useless when all it does is clip velocity?
            //if (_surfer.GroundObject != null)
            ////if (!_surfer.MoveData.JustGrounded && !_surfer.MoveData.Surfing && _surfer.GroundObject != null)
            //{
            //    //SurfPhysics.Reflect(_surfer, _deltaTime);
            //}
        }
예제 #5
0
        private Vector3 GroundInputMovement()
        {
            GetWishValues(out Vector3 wishVel, out Vector3 wishDir, out float wishSpeed);
            wishSpeed *= _surfer.MoveData.WalkFactor;

            return(SurfPhysics.Accelerate(_surfer.MoveData.Velocity, wishDir,
                                          wishSpeed, _config.Accelerate, _deltaTime, _surfer.MoveData.SurfaceFriction));
        }
예제 #6
0
        private Vector3 AirInputMovement()
        {
            GetWishValues(out Vector3 wishVel, out Vector3 wishDir, out float wishSpeed);
            var aircap = _surfer.MoveData.Surfing
                ? _config.AirCap * _config.AirCapSurfModifier
                : _config.AirCap;

            var result = SurfPhysics.AirAccelerate(_surfer.MoveData.Velocity, wishDir,
                                                   wishSpeed, _config.AirAccel, aircap, _deltaTime);

            return(result);
        }
예제 #7
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private Vector3 AirInputMovement()
        {
            Vector3 wishVel, wishDir;
            float   wishSpeed;

            GetWishValues(out wishVel, out wishDir, out wishSpeed);

            if (_config.clampAirSpeed && (wishSpeed != 0f && (wishSpeed > _config.maxSpeed)))
            {
                wishVel   = wishVel * (_config.maxSpeed / wishSpeed);
                wishSpeed = _config.maxSpeed;
            }

            return(SurfPhysics.AirAccelerate(_surfer.moveData.velocity, wishDir, wishSpeed, _config.airAcceleration, _config.airCap, _deltaTime));
        }
예제 #8
0
        private void CalculateNoclipVelocity()
        {
            AngleVectors(_surfer.MoveData.ViewAngles, out Vector3 forward, out Vector3 right, out Vector3 up);

            var wishVel = Vector3.zero;

            for (int i = 0; i < 3; i++)
            {
                wishVel[i] = forward[i] * _surfer.MoveData.ForwardMove + right[i] * _surfer.MoveData.SideMove;
            }
            var wishDir = wishVel.normalized;

            _surfer.MoveData.Velocity += wishDir * _config.NoclipSpeed;
            SurfPhysics.Friction(ref _surfer.MoveData.Velocity, _config.StopSpeed, _config.NoclipFriction, _deltaTime);
        }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private Vector3 GroundInputMovement()
        {
            Vector3 wishVel, wishDir;
            float   wishSpeed;

            GetWishValues(out wishVel, out wishDir, out wishSpeed);

            if ((wishSpeed != 0.0f) && (wishSpeed > _config.MaxSpeed))
            {
                wishVel  *= _config.MaxSpeed / wishSpeed;
                wishSpeed = _config.MaxSpeed;
            }

            wishSpeed *= _surfer.MoveData.WalkFactor;

            return(SurfPhysics.Accelerate(_surfer.MoveData.Velocity, wishDir,
                                          wishSpeed, _config.Accel, _deltaTime, _surfer.MoveData.SurfaceFriction));
        }
예제 #10
0
        private void IncrementOrigin(Vector3 amount)
        {
            _surfer.MoveData.PreviousOrigin = _surfer.MoveData.Origin;
            _surfer.MoveData.Origin        += amount;

            if (_surfer.MoveType == MoveType.Noclip && !_config.NoclipCollide)
            {
                return;
            }

            SurfPhysics.ResolveCollisions(_surfer);

            var prevOrigin       = _surfer.MoveData.PreviousOrigin;
            var newOrigin        = _surfer.MoveData.Origin;
            var movementThisStep = newOrigin - prevOrigin;
            var newMovement      = movementThisStep;

            if (movementThisStep.magnitude >= _surfer.Collider.bounds.extents.x)
            {
                var center = prevOrigin;
                center.y += _surfer.Collider.bounds.extents.y;

                var hitCount = Physics.BoxCastNonAlloc(center: center,
                                                       halfExtents: _surfer.Collider.bounds.extents * 0.5f,
                                                       direction: movementThisStep.normalized,
                                                       orientation: Quaternion.identity,
                                                       results: _hitCache,
                                                       maxDistance: movementThisStep.magnitude,
                                                       layerMask: SurfPhysics.GroundLayerMask,
                                                       queryTriggerInteraction: QueryTriggerInteraction.Ignore);

                if (hitCount > 0)
                {
                    for (int i = 0; i < hitCount; i++)
                    {
                        newMovement += _hitCache[i].normal * (movementThisStep.magnitude - _hitCache[i].distance);
                        SurfPhysics.ClipVelocity(_surfer.MoveData.Velocity, _hitCache[i].normal, ref _surfer.MoveData.Velocity, 1.01f);
                    }
                    _surfer.MoveData.Origin = prevOrigin + newMovement;
                }
            }
        }
예제 #11
0
        private void CalculateWalkVelocity(float modifier = 1.0f)
        {
            if (_surfer.GroundObject == null)
            {
                _surfer.MoveData.Velocity += AirInputMovement() * modifier;
                if (_surfer.MoveData.Buttons.HasFlag(InputActions.Brake))
                {
                    var vely = _surfer.MoveData.Velocity.y;
                    SurfPhysics.Friction(ref _surfer.MoveData.Velocity, 0f, _config.BrakeSpeed, _deltaTime);
                    _surfer.MoveData.Velocity.y = vely;
                }
            }
            else
            {
                _surfer.MoveData.Velocity += GroundInputMovement() * modifier;

                var friction  = _surfer.MoveData.SurfaceFriction * _config.Friction;
                var stopSpeed = _config.StopSpeed;
                SurfPhysics.Friction(ref _surfer.MoveData.Velocity, stopSpeed, friction, _deltaTime);
            }
        }
예제 #12
0
        private void ApplyMomentum()
        {
            if (!_surfer.MoveData.Momentum && _surfer.MoveData.BaseVelocity != Vector3.zero)
            {
                _surfer.MoveData.Velocity    += (1.0f + (_deltaTime * 0.5f)) * _surfer.MoveData.BaseVelocity;
                _surfer.MoveData.BaseVelocity = Vector3.zero;

                if (_surfer.MoveData.MomentumModifier != Vector3.zero)
                {
                    SurfPhysics.ClipVelocity(_surfer.MoveData.Velocity, _surfer.MoveData.MomentumModifier, ref _surfer.MoveData.Velocity, 1.0f);
                    SurfPhysics.ClipVelocity(_surfer.MoveData.BaseVelocity, _surfer.MoveData.MomentumModifier, ref _surfer.MoveData.BaseVelocity, 1.0f);
                    _surfer.MoveData.MomentumModifier = Vector3.zero;
                }
            }
            else if (_surfer.MoveData.Momentum)
            {
                CheckSlope();
            }

            _surfer.MoveData.Momentum = false;
        }
예제 #13
0
        private void UpdateRotation()
        {
            var   angles = MoveData.ViewAngles;
            float mx     = (Input.GetAxis("Mouse X") * XSens * .02200f);
            float my     = Input.GetAxis("Mouse Y") * YSens * .02200f;
            var   rot    = angles + new Vector3(-my, mx, 0f);

            rot.x = SurfPhysics.ClampAngle(rot.x, -89f, 89f);

            var yaw = 0;

            if (Input.GetKey(YawLeft))
            {
                yaw = -YawSpeed;
            }
            else if (Input.GetKey(YawRight))
            {
                yaw = YawSpeed;
            }

            rot.y += yaw * Time.deltaTime;
            Camera.transform.rotation = Quaternion.Euler(rot);
        }
        /// <summary>
        ///
        /// </summary>
        private void CalculateMovementVelocity()
        {
            switch (_surfer.moveType)
            {
            case MoveType.Walk:

                if (_surfer.groundObject == null)
                {
                    /*
                     * // AIR MOVEMENT
                     */

                    wasSliding = false;

                    // apply movement from input
                    _surfer.moveData.velocity += AirInputMovement();

                    // let the magic happen
                    SurfPhysics.Reflect(ref _surfer.moveData.velocity, _surfer.collider, _surfer.moveData.origin,
                                        _deltaTime);

                    if (_surfer.moveData.wishJump && jumpsLeft > 0)
                    {
                        jumpsLeft--;
                        ApplyFriction(0.0f, true, false);
                        _surfer.moveData.velocity.y = 0;
                        Jump();
                    }
                }
                else
                {
                    /*
                     * //  GROUND MOVEMENT
                     */

                    // Sliding
                    if (!wasSliding)
                    {
                        slideDirection = new Vector3(_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z)
                                         .normalized;
                        slideSpeedCurrent = Mathf.Max(_config.maximumSlideSpeed,
                                                      new Vector3(_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z).magnitude);
                    }

                    sliding = false;
                    if (_surfer.moveData.velocity.magnitude > _config.minimumSlideSpeed &&
                        _surfer.moveData.slidingEnabled && _surfer.moveData.crouching && slideDelay <= 0f)
                    {
                        if (!wasSliding)
                        {
                            slideSpeedCurrent = Mathf.Clamp(slideSpeedCurrent * _config.slideSpeedMultiplier,
                                                            _config.minimumSlideSpeed, _config.maximumSlideSpeed);
                        }

                        sliding    = true;
                        wasSliding = true;
                        SlideMovement();
                        //return;
                    }
                    else
                    {
                        if (slideDelay > 0f)
                        {
                            slideDelay -= _deltaTime;
                        }

                        if (wasSliding)
                        {
                            slideDelay = _config.slideDelay;
                        }

                        wasSliding = false;
                    }

                    float fric  = crouching ? _config.crouchFriction : _config.friction;
                    float accel = crouching ? _config.crouchAcceleration : _config.acceleration;
                    float decel = crouching ? _config.crouchDeceleration : _config.deceleration;

                    // Get movement directions
                    Vector3 forward = Vector3.Cross(groundNormal, -playerTransform.right);
                    Vector3 right   = Vector3.Cross(groundNormal, forward);

                    float speed = _surfer.moveData.sprinting ? _config.sprintSpeed : _config.walkSpeed;
                    if (crouching)
                    {
                        speed = _config.crouchSpeed;
                    }

                    Vector3 _wishDir;

                    // Jump and friction
                    if (_surfer.moveData.wishJump)
                    {
                        ApplyFriction(0.0f, true, true);
                        Jump();
                        return;
                    }
                    else
                    {
                        ApplyFriction(1.0f * frictionMult, true, true);
                    }

                    float forwardMove = _surfer.moveData.verticalAxis;
                    float rightMove   = _surfer.moveData.horizontalAxis;

                    _wishDir = forwardMove * forward + rightMove * right;
                    _wishDir.Normalize();
                    Vector3 moveDirNorm = _wishDir;

                    Vector3 forwardVelocity = Vector3.Cross(groundNormal,
                                                            Quaternion.AngleAxis(-90, Vector3.up) * new Vector3(_surfer.moveData.velocity.x, 0f,
                                                                                                                _surfer.moveData.velocity.z));

                    // Set the target speed of the player
                    float _wishSpeed = _wishDir.magnitude;
                    _wishSpeed *= speed;

                    // Accelerate
                    float yVel = _surfer.moveData.velocity.y;
                    Accelerate(_wishDir, _wishSpeed, accel * Mathf.Min(frictionMult, 1f), false);

                    float maxVelocityMagnitude = _config.maxVelocity;
                    _surfer.moveData.velocity = Vector3.ClampMagnitude(
                        new Vector3(_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z),
                        maxVelocityMagnitude);
                    _surfer.moveData.velocity.y = yVel;

                    // Calculate how much slopes should affect movement
                    float yVelocityNew = forwardVelocity.normalized.y *
                                         new Vector3(_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z)
                                         .magnitude;

                    // Apply the Y-movement from slopes
                    _surfer.moveData.velocity.y = yVelocityNew * (_wishDir.y < 0f ? 1.2f : 1.0f);
                    float removableYVelocity = _surfer.moveData.velocity.y - yVelocityNew;
                }

                break;
            } // END OF SWITCH STATEMENT
        }
예제 #15
0
        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            if (_surfer.moveData.laddersEnabled && !_surfer.moveData.climbingLadder)
            {
                // Look for ladders
                LadderCheck(new Vector3(1f, 0.95f, 1f), _surfer.moveData.velocity * Mathf.Clamp(Time.deltaTime * 2f, 0.025f, 0.25f));
            }

            if (_surfer.moveData.laddersEnabled && _surfer.moveData.climbingLadder)
            {
                LadderPhysics();
            }
            else if (!_surfer.moveData.underwater)
            {
                if (_surfer.moveData.velocity.y <= 0f)
                {
                    jumping = false;
                }

                // apply gravity
                if (_surfer.groundObject == null)
                {
                    _surfer.moveData.velocity.y -= (_surfer.moveData.gravityFactor * _config.gravity * _deltaTime);
                    _surfer.moveData.velocity.y += _surfer.baseVelocity.y * _deltaTime;
                }

                // input velocity, check for ground
                CheckGrounded();
                CalculateMovementVelocity();
            }
            else
            {
                // Do underwater logic
                UnderwaterPhysics();
            }

            float yVel = _surfer.moveData.velocity.y;

            _surfer.moveData.velocity.y = 0f;
            _surfer.moveData.velocity   = Vector3.ClampMagnitude(_surfer.moveData.velocity, _config.maxVelocity);
            speed = _surfer.moveData.velocity.magnitude;
            _surfer.moveData.velocity.y = yVel;

            if (_surfer.moveData.velocity.sqrMagnitude == 0f)
            {
                // Do collisions while standing still
                SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, _surfer.collider.transform.localPosition, 1f, _surfer.moveData.stepOffset, _surfer);
            }
            else
            {
                float   maxDistPerFrame   = 0.2f;
                Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime;
                float   velocityDistLeft  = velocityThisFrame.magnitude;
                float   initialVel        = velocityDistLeft;
                while (velocityDistLeft > 0f)
                {
                    float amountThisLoop = Mathf.Min(maxDistPerFrame, velocityDistLeft);
                    velocityDistLeft -= amountThisLoop;

                    // increment origin
                    Vector3 velThisLoop = velocityThisFrame * (amountThisLoop / initialVel);
                    _surfer.moveData.origin += velThisLoop;

                    // don't penetrate walls
                    SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, _surfer.collider.transform.localPosition, amountThisLoop / initialVel, _surfer.moveData.stepOffset, _surfer);
                }
            }

            _surfer.moveData.groundedTemp = _surfer.moveData.grounded;

            _surfer = null;
        }
예제 #16
0
        private bool CheckGrounded()
        {
            var wasSurfing = _surfer.MoveData.Surfing;

            _surfer.MoveData.SurfaceFriction = 1f;
            _surfer.MoveData.Surfing         = false;
            _surfer.MoveData.Sliding         = false;

            var trace             = BoxCastToFloor(.1f, .99f);
            var movingUp          = _surfer.MoveData.Velocity.y > 0;
            var goingAgainstSlope = false;
            var quickJump         = false;

            if (trace.HitCollider != null)
            {
                var slopeDir = Vector3.Cross(Vector3.up, Vector3.Cross(Vector3.up, trace.PlaneNormal));
                var dot      = Vector3.Dot(_surfer.MoveData.Velocity.normalized, slopeDir);
                goingAgainstSlope = dot > 0;

                if (trace.PlaneNormal.y <= SurfPhysics.SurfSlope)
                {
                    _surfer.MoveData.Surfing    = true;
                    _surfer.MoveData.SurfNormal = trace.PlaneNormal;
                }
                else if (goingAgainstSlope &&
                         dot >= _config.SlideDot)
                {
                    var tempVel = _surfer.MoveData.Velocity;
                    SurfPhysics.ClipVelocity(tempVel, trace.PlaneNormal, ref tempVel, 1.0f);
                    if (tempVel.y > _config.JumpPower * _config.SlideFactor)
                    {
                        _surfer.MoveData.Sliding = true;
                    }
                }
                quickJump = _surfer.GroundObject == null && !goingAgainstSlope && movingUp && trace.Distance < _surfer.MoveData.Velocity.y;
            }

            if (MovingUpRapidly() ||
                trace.HitCollider == null ||
                _surfer.MoveData.Surfing ||
                _surfer.MoveData.Sliding ||
                _surfer.MoveData.GravityFactor < 0 ||
                quickJump ||
                (_surfer.MoveType == MoveType.Ladder && movingUp))
            {
                _surfer.MoveData.GroundTest = 0;
                SetGround(null);
                return(false);
            }
            else
            {
                if (wasSurfing && _surfer.MoveData.GroundTest == 0)
                {
                    _surfer.MoveData.GroundTest++;
                    SetGround(null);
                    return(false);
                }
                _surfer.MoveData.GroundTest = 0;
                SetGround(trace.HitCollider.gameObject);
                _surfer.MoveData.Origin.y = trace.HitPoint.y + HammerScale;

                // slant boost, but only if velocity is away from slope
                if (_surfer.MoveData.JustGrounded)
                {
                    if (!goingAgainstSlope)
                    {
                        //SurfPhysics.ClipVelocity(_surfer.MoveData.Velocity, trace.PlaneNormal, ref _surfer.MoveData.Velocity, 1.0f);
                        SurfPhysics.Reflect(_surfer, _deltaTime, trace.PlaneNormal);
                    }
                    _surfer.MoveData.Velocity.y = 0;
                }

                return(true);
            }
        }