Better patrolling

This is a revised patrolling state that, among other things, omits the crashing and hanging present in the vanilla code

Author: Hanfling

state Patrolling
{
    function SetFall()
    {
        StartFalling('Patrolling', 'ContinuePatrol');
    }

    function HitWall(vector HitNormal, actor Wall)
    {
        if (Physics == PHYS_Falling)
            return;
        Global.HitWall(HitNormal, Wall);
        CheckOpenDoor(HitNormal, Wall);
    }

    function AnimEnd()
    {
        PlayWaiting();
    }

    function PatrolPoint PickStartPoint()
    {
        local NavigationPoint nav;
        local PatrolPoint     curNav;
        local float           curDist;
        local PatrolPoint     closestNav;
        local float           closestDist;

        nav = Level.NavigationPointList;
        while (nav != None)
        {
            nav.visitedWeight = 0;
            nav = nav.nextNavigationPoint;
        }

        closestNav  = None;
        closestDist = 100000;
        nav = Level.NavigationPointList;
        while (nav != None)
        {
            curNav = PatrolPoint(nav);
            if ((curNav != None) && (curNav.Tag == OrderTag))
            {
                while (curNav != None)
                {
                    if (curNav.visitedWeight != 0)  // been here before
                        break;
                    curDist = VSize(Location - curNav.Location);
                    if ((closestNav == None) || (closestDist > curDist))
                    {
                        closestNav  = curNav;
                        closestDist = curDist;
                    }
                    curNav.visitedWeight = 1;
                    curNav = curNav.NextPatrolPoint;
                }
            }
            nav = nav.nextNavigationPoint;
        }

        return (closestNav);
    }

    function PickDestination()
    {
        if (PatrolPoint(destPoint) != None)
            destPoint = PatrolPoint(destPoint).NextPatrolPoint;
        else
            destPoint = PickStartPoint();
        if (destPoint == None)  // can't go anywhere...
            GotoState('Standing');
    }

    function BeginState()
    {
        StandUp();
        SetEnemy(None, EnemyLastSeen, true);
        Disable('AnimEnd');
        SetupWeapon(false);
        SetDistress(false);
        bStasis = false;
        SeekPawn = None;
        EnableCheckDestLoc(false);
    }

    function EndState()
    {
        EnableCheckDestLoc(false);
        Enable('AnimEnd');
        bStasis = true;
    }

Begin:
    destPoint = None;

Patrol:
    WaitForLanding();
    PickDestination();

Moving:
    // Move from pathnode to pathnode until we get where we're going
    if (destPoint != None)
    {
        if (!IsPointInCylinder(self, destPoint.Location, 16-CollisionRadius))
        {
            EnableCheckDestLoc(true);
            MoveTarget = FindPathToward(destPoint);

            if (MoveTarget != None)
            {
                while (MoveTarget != None)
                {
                    if (ShouldPlayWalk(MoveTarget.Location))
                        PlayWalking();
                    MoveToward(MoveTarget, GetWalkingSpeed());
                    CheckDestLoc(MoveTarget.Location, true);
                    if (MoveTarget == destPoint)
                        break;
                    MoveTarget = FindPathToward(destPoint);
                }
                if ((MoveTarget != None) && (MoveTarget != destPoint))
                {
                    SetOrders('Standing', 'None', False);
                    GoToState('Standing');
                }
            }
            //MADDERS: Shout out to Hanfling on this one.
            else
            {
                if (ShouldPlayWalk(destPoint.Location))
                    PlayWalking();
                MoveToward(destPoint, GetWalkingSpeed());
            }
            EnableCheckDestLoc(false);
        }
    }
    else
        Goto('Patrol');

Pausing:
    if (!bAlwaysPatrol)
        bStasis = true;
    Acceleration = vect(0, 0, 0);

    // Turn in the direction dictated by the WanderPoint, or a random direction
    if (PatrolPoint(destPoint) != None)
    {
        if ((PatrolPoint(destPoint).pausetime > 0) || (PatrolPoint(destPoint).NextPatrolPoint == None))
        {
            if (ShouldPlayTurn(Location + PatrolPoint(destPoint).lookdir))
                PlayTurning();
            TurnTo(Location + PatrolPoint(destPoint).lookdir);
            Enable('AnimEnd');
            TweenToWaiting(0.2);
            PlayScanningSound();
            sleepTime = PatrolPoint(destPoint).pausetime * ((-0.9*restlessness) + 1);
            Sleep(sleepTime);
            Disable('AnimEnd');
            FinishAnim();
        }
    }
    Goto('Patrol');

ContinuePatrol:
ContinueFromDoor:
    FinishAnim();
    PlayWalking();
    Goto('Moving');

}