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}");
        }
    }
        public override void Tick()
        {
            ViewOffset = Vector3.Up * EyeHeight;

            UpdateBBox();

            ViewOffset += TraceOffset;

            RestoreGroundPos();

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

            Swimming = Player.WaterLevel.Fraction > 0.6f;

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

                BaseVelocity = BaseVelocity.WithZ(0);
            }

            if (Input.Pressed(InputButton.Jump))
            {
                CheckJumpButton();
            }

            bool bStartOnGround = GroundEntity != null;

            if (bStartOnGround)
            {
                Velocity = Velocity.WithZ(0);

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

            WishVelocity = new Vector3(Input.Forward, Input.Left, 0);

            var inSpeed = WishVelocity.Length.Clamp(0, 1);

            WishVelocity *= Input.Rot;

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

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

            Duck.PreTick();

            bool stayOnGround = false;

            OnPreTickMove();

            if (Swimming)
            {
                ApplyFriction(1);
                WaterMove();
            }
            else if (GroundEntity != null)
            {
                stayOnGround = true;
                WalkMove();
            }
            else
            {
                AirMove();
            }

            CategorizePosition(stayOnGround);

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

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

            SaveGroundPos();
        }