Named arguments are a solution to precisely this issue. With optional arguments with default value, you get to do precisely what was being done in your Lua code but with self documenting code.
I personally believe very strongly that people shouldn’t use programming languages lacking basic functionalities.
Or not use them without tooling?
I believe IDE's had the feature of showing me the function header with a mouse hover 20+ years ago.
It amazes me the contortions that Golang devs (me included) go through to get something approaching the keyword arguments from python.
It's honestly what I miss the most about python: keyword args, keyword-only args, positional-only args.
What I don't miss is the unholy abomination of *kwargs...
You can also document the argument name inline for languages with block comments but no named args.
You can but it’s not the same because the names of named arguments are also present at the call site.
Named arguments don't stop the deeper problem, which is that N booleans have 2^N possible states. As N increases it's rare for all those combinations to be valid. Just figuring out the truth table might be challenging enough, then there's the question of whether the caller or callee is responsible for enforcing it. And either way you have to document and test it.
Enums are better because you can carve out precisely the state space you want and no more.
That's not a problem per se. It may very well be that you're configuring the behavior of something with a bunch of totally independent on/off switches. Replacing n booleans with an enum with 2^n values is just as wrong as replacing a 5-valued enum with 3 booleans that cannot be validly set independently.