/// <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); }
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); }