Spaghetti code is never the right answer. Patterns are good at cleaning up spaghetti code, but just having a well thought out design can achieve the same thing.
With respect to the state-machine question: I personally find them to be very useful. For a public facing app I created, I refactored to use a state-chart (which I think is the same thing as the state-machine) and noticed the benefits you mentioned. It is a really useful abstraction, because it allows you to separate the concern of handling events out into a separate component. With this, bugs go away because the state-chart implicitly knows what a user can do where, and since the events are only handled in the right place, you can't really perform an invalid action. Also, using the state-chart allowed me to simplify the code because I could pull all the event handling code out of where it was and put it where it in one place where it was supposed to be -- in other words, other components weren't complicated by also having event handlers on them.
A picture is worth a thousand works -- Here is the design I came up with:

With this, anyone who looks at it knows exactly how the app behaves at a high level. Its hard to break this, because like I said, you can't get to an invalid state because the event handlers control exactly where you can go; if you can get to an invalid state, its an implementation bug that is easily fixed. Also, the code cleansing benefits are enormous. For example, with the state chart, whenever I enter any paused state, I can do things like stop the clock, put a mask on the board, etc. Its a few lines of code in one place -- because when i enter a substate of paused the chart goes thru the parent state first. without the statechart, I would have to do that code everywhere an event was handled.
I don't know if it needs to be a language level feature, but having a well implemented framework is nice.