Have to agree with some key points made in >>3482
. Inheritance is far less important than textbooks and people at job interviews give it credit for. Controlling access to data and grouping the data via a common interface is the real meat of it. If you don't need to organize data and control access to it, there's really not a massive need for objects in your code.
There is a case for inheritance, of course, especially as you move to large programs. Especially those with GUIs. And factories can help with abstraction. It's nice to be able to generate an object as needed and be able to interact with it using the same interface for all the children without regard for the underpinnings. But it's also a lot of preparation.
The worst thing is developers who worship Object Oriented as though it were a god. Absolute brainlets who think a 50 line script is improved by 300 lines of handlers to abstract something you set once. It could have been a variable. No harm is done. No additional validation is needed. If you're that concerned, add a check or an assert. Adding objects where they're not needed just adds complexity for no reason.
If you look at a big block of spaghetti, or worse, multiple blocks of repeated copypasted spaghetti, and you say "it would be easier just to track each of these and manage them with basic rules", it's time to use an object. Segregate the data, mark how to handle it, and then have that function handle it properly for that subtype. You just condensed spaghetti into one line and it probably cost you 50 in boilerplate, but you never have to worry again.
Procedural is fine and great for scripts, but there does come a point when sifting through data or trying to ensure certain variables comply with rules is just easier to do with objects. Procedural has some severe limitations when it comes to tracking state over the long term. Like you said, you end up reinventing the wheel more often than not. Sometimes you really just want a linked list, and writing one in C is a lot of extra work with a lot less guarantees. This is one reason I use C++ even for programs that would be fine in C: it's nice to just include existing data structures and run with them.