Your question seems indeed a bit confusing. I assume you are asking about the problem, how some specific code piece (e.g. the function responsible for firing a bullet within the mob unit) should get to the information about "how to fire the bullet" and "what bullet type" and so on?
Here are some solutions:
Just use globals and get over it ;)
In gaming development (and also in many other code development areas outside of universities ;)), people are usually very pragmatic (some call this "old-fashioned" :)). You see global variables and "global manager" very often.
So for example if a unit needs to fire a bullet with some sparkles, its common to just write something like this (yes, even hardcoded values. But usually these are only ID's for the real values stored in some table etc..):
BulletManager::instance->FireBullet("biggun.bullet");
ParticleEffectManager::instance->SpawnParticle("smoke.xml");
That doesn't mean that game developer don't know about the risks or problems behind it and in many post-mortem meetings, the need for "less global stuff" is expressed by at least one of the coders ;).
Said that, there are a couple of other ways how to solve this kind of problem - academic and real-world ones:
Pass the stuff to the constructor
Just pass down relevant managers (or "states" as you call it) to the objects, usually via Constructor or as setter right after construction. (This is sometimes called "dependency injection", as the "tools get injected into the object"). Every object remembers the managers it needs to perform its work. Yes, you already said that this sounds weird and memory wastefull, but stop a second and think about the real impact. You have how many mobs? 1000? 5000 at maximum? Each mob stores 5 pointer is how much memory? Usually irrelevant. (If you scream "cache misses" now: Nobody said the pointer have to be stored together with the other objects properties. You should always consider grouping data in memory together that needs to be processed together. That is as true for Position vectors as it is for pointer to scenes.)
One common mistake with this approach is, to "pass things to create the tools".
Coder start to complain that their mob constructor now takes 20 arguments, because they need to pass 5 to create or parametrize the particle engine, 10 to forward to the physic engine to raycast, and another 5 to pass to their created Bullets. And for every tweak in one of the subsystems, they need to touch dozends of constructors and do hundrets of lines of boilerplate blabla...
Don't do this. Pass the tools instead. So for this example, your would send only 3 parameter: A particle spawner, a physic engine handler and a BulletFactory.
Usually, this design leads to a lot fewer global "manager" instances and a lot more "personalized factories" that can spawn particles for this particular unit (or even this particular use within the unit).
Pass as arguments when calling the function
If the storage of the pointer within each object is too much or you often need to use different contextes with the same object, then you might pass the relevant information to the function that does the work.
This approach is by far most often used for library functions.
Know someone who knows it
You can hide the complexity of how to get all the things you need in other classes like the base class or an single passed "context" class. I think this is some kind of compromise between the first answer (global statics) and the others.