/// <summary>
        ///
        /// </summary>
        /// <param name="velocity"></param>
        /// <param name="origin"></param>
        /// <param name="firstDestination"></param>
        /// <param name="firstTrace"></param>
        /// <returns></returns>
        public static int Reflect(ref Vector3 velocity, Collider collider, Vector3 origin, float deltaTime)
        {
            float d;
            var   newVelocity      = Vector3.zero;
            var   blocked          = 0;        // Assume not blocked
            var   numplanes        = 0;        //  and not sliding along any planes
            var   originalVelocity = velocity; // Store original velocity
            var   primalVelocity   = velocity;

            var allFraction = 0f;
            var timeLeft    = deltaTime; // Total time for this movement operation.

            for (int bumpcount = 0; bumpcount < NumBumps; bumpcount++)
            {
                if (velocity.magnitude == 0f)
                {
                    break;
                }

                // Assume we can move all the way from the current origin to the
                //  end point.
                var end   = VectorExtensions.VectorMa(origin, timeLeft, velocity);
                var trace = Tracer.TraceCollider(collider, origin, end, GroundLayerMask);

                allFraction += trace.Fraction;

                if (trace.Fraction > 0)
                {
                    // actually covered some distance
                    originalVelocity = velocity;
                    numplanes        = 0;
                }

                // If we covered the entire distance, we are done
                //  and can return.
                if (trace.Fraction == 1)
                {
                    break;      // moved the entire distance
                }

                // If the plane we hit has a high z component in the normal, then
                //  it's probably a floor
                if (trace.PlaneNormal.y > SurfSlope)
                {
                    blocked |= 1;       // floor
                }
                // If the plane has a zero z component in the normal, then it's a
                //  step or wall
                if (trace.PlaneNormal.y == 0)
                {
                    blocked |= 2;       // step / wall
                }

                // Reduce amount of m_flFrameTime left by total time left * fraction
                //  that we covered.
                timeLeft -= timeLeft * trace.Fraction;

                // Did we run out of planes to clip against?
                if (numplanes >= MaxClipPlanes)
                {
                    // this shouldn't really happen
                    //  Stop our movement if so.
                    velocity = Vector3.zero;
                    //Con_DPrintf("Too many planes 4\n");
                    break;
                }

                // Set up next clipping plane
                _planes[numplanes] = trace.PlaneNormal;
                numplanes++;

                // modify original_velocity so it parallels all of the clip planes
                //

                // reflect player velocity
                // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place
                //  and pressing forward and nobody was really using this bounce/reflection feature anyway...
                if (numplanes == 1)
                {
                    for (int i = 0; i < numplanes; i++)
                    {
                        if (_planes[i][1] > SurfSlope)
                        {
                            // floor or slope
                            return(blocked);
                            //ClipVelocity(originalVelocity, _planes[i], ref newVelocity, 1f);
                            //originalVelocity = newVelocity;
                        }
                        else
                        {
                            ClipVelocity(originalVelocity, _planes[i], ref newVelocity, 1f);
                        }
                    }
                    velocity         = newVelocity;
                    originalVelocity = newVelocity;
                }
                else
                {
                    int i = 0;
                    for (i = 0; i < numplanes; i++)
                    {
                        ClipVelocity(originalVelocity, _planes[i], ref velocity, 1);

                        int j = 0;

                        for (j = 0; j < numplanes; j++)
                        {
                            if (j != i)
                            {
                                // Are we now moving against this plane?
                                if (Vector3.Dot(velocity, _planes[j]) < 0)
                                {
                                    break;
                                }
                            }
                        }
                        if (j == numplanes)  // Didn't have to clip, so we're ok
                        {
                            break;
                        }
                    }

                    // Did we go all the way through plane set
                    if (i != numplanes)
                    {   // go along this plane
                        // pmove.velocity is set in clipping call, no need to set again.
                        ;
                    }
                    else
                    {   // go along the crease
                        if (numplanes != 2)
                        {
                            velocity = Vector3.zero;
                            break;
                        }
                        var dir = Vector3.Cross(_planes[0], _planes[1]).normalized;
                        d        = Vector3.Dot(dir, velocity);
                        velocity = dir * d;
                    }

                    //
                    // if original velocity is against the original velocity, stop dead
                    // to avoid tiny occilations in sloping corners
                    //
                    d = Vector3.Dot(velocity, primalVelocity);
                    if (d <= 0f)
                    {
                        //Con_DPrintf("Back\n");
                        velocity = Vector3.zero;
                        break;
                    }
                }
            }

            if (allFraction == 0f)
            {
                velocity = Vector3.zero;
            }

            // Check if they slammed into a wall
            //float fSlamVol = 0.0f;

            //var primal2dLen = new Vector2(primal_velocity.x, primal_velocity.z).magnitude;
            //var vel2dLen = new Vector2(_moveData.Velocity.x, _moveData.Velocity.z).magnitude;
            //float fLateralStoppingAmount = primal2dLen - vel2dLen;
            //if (fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED * 2.0f)
            //{
            //    fSlamVol = 1.0f;
            //}
            //else if (fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED)
            //{
            //    fSlamVol = 0.85f;
            //}

            //PlayerRoughLandingEffects(fSlamVol);

            return(blocked);
        }
Beispiel #2
0
        private bool LadderMove()
        {
            Vector3 wishDir = Vector3.zero;

            if (_surfer.MoveType == MoveType.Ladder)
            {
                wishDir = -_surfer.MoveData.LadderNormal;
            }
            else
            {
                if (_surfer.MoveData.ForwardMove != 0 || _surfer.MoveData.SideMove != 0)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        wishDir[i] = _surfer.Forward[i] * _surfer.MoveData.ForwardMove + _surfer.Right[i] * _surfer.MoveData.SideMove;
                    }
                    wishDir = wishDir.normalized;
                }
                else
                {
                    return(false);
                }
            }

            var start = _surfer.MoveData.Origin;

            start.y += _surfer.Collider.bounds.extents.y;
            var end   = VectorExtensions.VectorMa(start, _config.LadderDistance, wishDir);
            var trace = Tracer.TraceBoxForTag(_surfer.Collider, start, end, ~0, "Ladder");

            if (trace.HitCollider == null)
            {
                return(false);
            }

            _surfer.MoveType = MoveType.Ladder;
            _surfer.MoveData.LadderNormal = trace.PlaneNormal;

            var climbSpeed = _config.MaxClimbSpeed;

            if (_surfer.MoveData.Buttons.HasFlag(InputActions.Jump))
            {
                _surfer.MoveType          = MoveType.Walk;
                _surfer.MoveData.Velocity = trace.PlaneNormal * _config.JumpOffLadderSpeed;
            }
            else
            {
                float forwardSpeed = 0, rightSpeed = 0;

                if (_surfer.MoveData.Buttons.HasFlag(InputActions.MoveBack))
                {
                    forwardSpeed -= climbSpeed;
                }
                if (_surfer.MoveData.Buttons.HasFlag(InputActions.MoveForward))
                {
                    forwardSpeed += climbSpeed;
                }
                if (_surfer.MoveData.Buttons.HasFlag(InputActions.MoveLeft))
                {
                    rightSpeed -= climbSpeed;
                }
                if (_surfer.MoveData.Buttons.HasFlag(InputActions.MoveRight))
                {
                    rightSpeed += climbSpeed;
                }

                if (forwardSpeed != 0 || rightSpeed != 0)
                {
                    var     fwd = Quaternion.Euler(_surfer.MoveData.ViewAngles) * Vector3.forward;
                    var     right = Quaternion.Euler(_surfer.MoveData.ViewAngles) * Vector3.right;
                    Vector3 velocity, perp, cross, lateral, tmp;
                    velocity = fwd * forwardSpeed + rightSpeed * right;
                    tmp      = Vector3.zero;
                    tmp[1]   = HammerScale;
                    perp     = Vector3.Cross(tmp, trace.PlaneNormal).normalized;
                    float normal = Vector3.Dot(velocity, trace.PlaneNormal);
                    cross   = trace.PlaneNormal * normal;
                    lateral = velocity - cross;
                    tmp     = Vector3.Cross(trace.PlaneNormal, perp);

                    // if cstrike.dll
                    float tmpDist  = Vector3.Dot(tmp, lateral);
                    float perpDist = Vector3.Dot(perp, lateral);
                    var   angleVec = perp * perpDist;
                    angleVec += cross;
                    angleVec.Normalize();
                    float angleDot = Vector3.Dot(angleVec, trace.PlaneNormal);
                    if (angleDot < _config.LadderAngle)
                    {
                        lateral = (tmp * tmpDist) + (perp * _config.LadderDampen * perpDist);
                    }
                    // endif

                    _surfer.MoveData.Velocity = lateral + -normal * tmp;

                    if (_surfer.GroundObject != null && normal > 0)  // On ground moving away from the ladder
                    {
                        _surfer.MoveData.Velocity += _config.MaxClimbSpeed * trace.PlaneNormal;
                    }
                }
                else
                {
                    _surfer.MoveData.Velocity = Vector3.zero;
                }
            }

            return(true);
        }