/// <summary> /// We adjust the ball's linear / angular damping based on the surface. /// This can be done clientside for prediction. /// </summary> protected void AdjustDamping() { var downTrace = Trace.Ray(Position, Position + Vector3.Down * OOBBox.Size.z); downTrace.HitLayer(CollisionLayer.Solid); downTrace.Ignore(this); var downTraceResult = downTrace.Run(); if (Debug) { DebugOverlay.Line(downTraceResult.StartPos, downTraceResult.EndPos); // if ( downTraceResult.Entity.IsValid() ) // DebugOverlay.Text( downTraceResult.StartPos, $"e: {downTraceResult.Entity.EngineEntityName}" ); } // We are in the air, do nothing? (Maybe we could adjust something to make ball airtime feel nicer?) if (!downTraceResult.Hit) { return; } // See if we're on a flat surface by checking the dot product of the surface normal. if (downTraceResult.Normal.Dot(Vector3.Up).AlmostEqual(1, 0.001f)) { switch (downTraceResult.Surface.Name) { case "minigolf.sand": PhysicsBody.LinearDamping = 2.5f; PhysicsBody.AngularDamping = 2.5f; break; case "minigolf.ice": PhysicsBody.LinearDamping = 0.25f; PhysicsBody.AngularDamping = 0.00f; break; default: PhysicsBody.LinearDamping = DefaultLinearDamping; PhysicsBody.AngularDamping = DefaultAngularDamping; break; } if (downTraceResult.Entity is SpeedBoost speedBoost) { // TODO: Multiply by delta time var velocity = PhysicsBody.Velocity; velocity += Angles.AngleVector(speedBoost.MoveDir) * speedBoost.SpeedMultiplier; PhysicsBody.Velocity = velocity; } return; } // We must be on a hill, we can detect if it's up hill or down hill by doing a forward trace var trace = Trace.Ray(Position, Position + PhysicsBody.Velocity.WithZ(0)); trace.HitLayer(CollisionLayer.Debris); trace.Ignore(this); var traceResult = trace.Run(); if (traceResult.Hit) { PhysicsBody.LinearDamping = 0.015f; PhysicsBody.AngularDamping = 2.00f; return; } PhysicsBody.LinearDamping = 0.0f; PhysicsBody.AngularDamping = 1.0f; }