void WriteDebugInfo()
        {
            BBox hull = GetHull();

            DebugOverlay.Box(Position + TraceOffset, hull.Mins, hull.Maxs, Color.Red);
            DebugOverlay.Box(Position, hull.Mins, hull.Maxs, Color.Blue);

            var lineOffset = Host.IsServer ? 10 : 0;

            DebugOverlay.ScreenText(lineOffset + 0, $"             Pos: {Position}");
            DebugOverlay.ScreenText(lineOffset + 1, $"             Vel: {Velocity} ({Velocity.Length:n0})");
            DebugOverlay.ScreenText(lineOffset + 2, $"    WishVelocity: {WishVelocity}");
            DebugOverlay.ScreenText(lineOffset + 3, $"    BaseVelocity: {BaseVelocity}");
            DebugOverlay.ScreenText(lineOffset + 4, $"        Rotation: {Rotation.Angles().pitch:n2},{Rotation.Angles().yaw:n2},{Rotation.Angles().roll:n2}");
        }
    public override void Simulate()
    {
        // Do fall damage stufftw
        if (Velocity.z < 0)
        {
            takeFallDamage    = true;
            previousZVelocity = Velocity.z;
        }
        else if (takeFallDamage && Velocity.z == 0)
        {
            takeFallDamage = false;
            TakeDmg();
        }

        EyePosLocal = Vector3.Up * (EyeHeight * Pawn.Scale);
        UpdateBBox();

        EyePosLocal += TraceOffset;
        EyeRot       = Input.Rotation;

        RestoreGroundPos();

        //Velocity += BaseVelocity * ( 1 + Time.Delta * 0.5f );
        //BaseVelocity = Vector3.Zero;

        //Rot = Rotation.LookAt( Input.Rotation.Forward.WithZ( 0 ), Vector3.Up );

        if (Unstuck.TestAndFix())
        {
            return;
        }

        // Check Stuck
        // Unstuck - or return if stuck

        // Set Ground Entity to null if  falling faster then 250

        // store water level to compare later

        // if not on ground, store fall velocity

        // player->UpdateStepSound( player->m_pSurfaceData, mv->GetAbsOrigin(), mv->m_vecVelocity )


        // RunLadderMode

        CheckLadder();
        Swimming = Pawn.WaterLevel.Fraction > 0.6f;

        //
        // Start Gravity
        //
        if (!Swimming && !IsTouchingLadder)
        {
            Velocity -= new Vector3(0, 0, Gravity * 0.5f) * Time.Delta;
            Velocity += new Vector3(0, 0, BaseVelocity.z) * Time.Delta;

            BaseVelocity = BaseVelocity.WithZ(0);
        }


        /*
         * if (player->m_flWaterJumpTime)
         *      {
         *              WaterJump();
         *              TryPlayerMove();
         *              // See if we are still in water?
         *              CheckWater();
         *              return;
         *      }
         */

        // if ( underwater ) do underwater movement

        if (AutoJump ? Input.Down(InputButton.Jump) : Input.Pressed(InputButton.Jump))
        {
            CheckJumpButton();
        }

        // Fricion is handled before we add in any base velocity. That way, if we are on a conveyor,
        //  we don't slow when standing still, relative to the conveyor.
        bool bStartOnGround = GroundEntity != null;

        //bool bDropSound = false;
        if (bStartOnGround)
        {
            //if ( Velocity.z < FallSoundZ ) bDropSound = true;

            Velocity = Velocity.WithZ(0);
            //player->m_Local.m_flFallVelocity = 0.0f;

            if (GroundEntity != null)
            {
                ApplyFriction(GroundFriction * SurfaceFriction);
            }
        }

        //
        // Work out wish velocity.. just take input, rotate it to view, clamp to -1, 1
        //
        WishVelocity = new Vector3(Input.Forward, Input.Left, 0);
        var inSpeed = WishVelocity.Length.Clamp(0, 1);

        WishVelocity *= Input.Rotation;

        if (!Swimming && !IsTouchingLadder)
        {
            WishVelocity = WishVelocity.WithZ(0);
        }

        WishVelocity  = WishVelocity.Normal * inSpeed;
        WishVelocity *= GetWishSpeed();

        Duck.PreTick();

        bool bStayOnGround = false;

        if (AttachedBalloons > 0)
        {
            ClearGroundEntity();
            Velocity = Velocity.WithZ(1 * AttachedBalloons * BalloonVelocity);
            AirMove();
        }
        else if (Swimming)
        {
            ApplyFriction(1);
            WaterMove();
        }
        else if (IsTouchingLadder)
        {
            LadderMove();
        }
        else if (GroundEntity != null)
        {
            bStayOnGround = true;
            WalkMove();
        }
        else
        {
            AirMove();
        }

        CategorizePosition(bStayOnGround);

        // FinishGravity
        if (!Swimming && !IsTouchingLadder)
        {
            Velocity -= new Vector3(0, 0, Gravity * 0.5f) * Time.Delta;
        }


        if (GroundEntity != null)
        {
            Velocity = Velocity.WithZ(0);
        }

        // CheckFalling(); // fall damage etc

        // Land Sound
        // Swim Sounds

        SaveGroundPos();

        if (Debug)
        {
            DebugOverlay.Box(Position + TraceOffset, mins, maxs, Color.Red);
            DebugOverlay.Box(Position, mins, maxs, Color.Blue);

            var lineOffset = 0;
            if (Host.IsServer)
            {
                lineOffset = 10;
            }

            DebugOverlay.ScreenText(lineOffset + 0, $"        Position: {Position}");
            DebugOverlay.ScreenText(lineOffset + 1, $"        Velocity: {Velocity}");
            DebugOverlay.ScreenText(lineOffset + 2, $"    BaseVelocity: {BaseVelocity}");
            DebugOverlay.ScreenText(lineOffset + 3, $"    GroundEntity: {GroundEntity} [{GroundEntity?.Velocity}]");
            DebugOverlay.ScreenText(lineOffset + 4, $" SurfaceFriction: {SurfaceFriction}");
            DebugOverlay.ScreenText(lineOffset + 5, $"    WishVelocity: {WishVelocity}");
        }
    }