Fernando Bevilacqua has a fantastic series on Understanding Steering Behaviors. While his code generates forces on sprites and doesn't directly apply to our throttle/steering controls, the theory is still applicable.

One of the beautiful features of Fernando's approach is that all of his steering behaviors are cumulative and combine to create fluid motion. We'll do the same by injecting a collision avoidance check after the vehicle calculates its navigation controls. This means it will avoid collisions when necessary but will resume traveling toward its destination otherwise.

Setting the End vector to some distance ahead will return a boolean if there's an obstacle. I once again made use of GetForwardSpeed() as the look-ahead length for simplicity. The faster the vehicle is traveling, the farther ahead it needs to check for obstacles to react to.

After experimentation, I projected two collision "sensors" on either side of the vehicle. When only one is used, slight angle differences between nearby vehicles may not trace a hit yet still collide:

Looks almost like tracer fire from side-mounted weapons...

As for "applying an avoidance force", our limited control options of throttle or steering become a blessing in disguise as we're reduced to two options to react: slow down or turn away.

Slowing down was simple to implement: set the throttle to -1. As soon as the obstacle is out of range, pathfinding resumes and they speed up again on their own. While this did reduce the number of collisions, it also caused the vehicles to spread out into a long line.

Steering away was only slightly more complicated. In this case, both sensors were necessary to decide which way to turn: away from the side closest to the detected collision. Also an improved reduction of collisions, but they could be going too fast to avoid a collision despite turning.

So implementing both became necessary and avoided most collisions while keeping them relatively close together:

The collision counter at the top of the preview is with avoidance disabled...

Getting Unstuck

While we're injecting safety checks, there's another that's desperately needed: getting unstuck when rammed against a wall or another vehicle.

This was simply a series of branches, basically the same thing you would do actually driving:

If I'm not stuck, constantly reset a StuckTimer

If my throttle is not 0 but my velocity (nearly) is 0, then I could be stuck; watch the StuckTimer

If I'm still not moving after 1 second, set Throttle and Steering opposite to whatever I was doing

After 1 second of doing the opposite, I'm not stuck

Our AI routine still looks manageable:

Our vehicles are fairly autonomous, so the last thing to implement before "Guns!" is enemy detection.