Here's an old post I made on the subject,
There's a half-reason, but it's way more complex than simply checking against a maximum range. Before you read any of the following, I challenge you NOT to take my word for it and study the code yourself, to see if we come to the same conclusions.
Yet, there's a point past which monsters won't fire missiles at the player. Keep studying the code until you find the reason why.
First of all, there's nothing causing most monsters to abort an attack if a target is already set AND they have already entered their firing state. They won't "yield" nor "chicken out" of it if e.g. their target gets out of range. Exceptions explained below.
The sequence is more or less: monsters execute A_Chase, they look for targets, and if they have one they run P_CheckMissileRange(). The player is a bit special in that he must be "detected" through the LOS functions, which may fail for other reasons which have more to do with a map's geometry or reject/bsp issues, rather than range. OK, in THAT ONE P_CheckMissileRange() function there are some range checks done but they are far from straightforward, and far from the only ones:
The corollary of the above? Barring some very special cases like Archviles, Revenants or immediate retaliation, the main limiting factor on STARTING ranged attacks is pure luck: ranged attacks have at most a 200/256 or 160/256 chance for cyberdemons of not being started at all.
- The only monsters which have some FIXED range limit that will prevent them from starting a ranged attack AT ALL are Archviles (at a ranges > 14*64 map units), and Revenants (won't use missile if closer than 196 map units, but there's an exception: read on).
- If a monster is actually ATTACKED by its target, it will fire back no matter the distance. THIS TRUMPS ALL FOLLOWING CHECKS, and in theory it trumps even the archvile attack, at least within P_CheckMissileRange()
- For all other monsters, the distance in map units is progressively divided by 2 after each check. After it's reduced to at most 200 or to 160 map units for cyberdemons, a call to P_Random() (!) is made, and if the result is smaller than the remaining dist value, then the attack is cancelled. That's right, PURE FUCKING LUCK.
- Apart from the above mentioned cases, there are no further range limiting checks that may cancel an attack.
WARNING: GORIER DETAILS FOLLOW
Of course, the larger the initial distance, the higher the chance that an attack will be aborted, which is however capped at 200/256 and 160/256 (about 75% and 60% accordingly). With sufficiently small distances, ranged attacks are never aborted, but even with the highest possible, the chance of starting them is always non-zero.
if (P_Random() < dist)
Assuming an Imp vs a Player:
In the case of revenants, cyberdemons, spider masterminds and lost souls, dist gets halved. This effectively DOUBLES the chances of starting an attack.
- P_CheckMissileRange() computes an initial value of dist which gets shifted >> 16 (from 16.16 fixed_t to 16-bit signed short).
- dist doesn't get halved in any of the following checks.
- Dist is capped at 200 map units.
- P_Random() is called. If its value is <dist, the attack is aborted.
So no matter the range, any monster has at most a 200/256 chance of aborting a very long range attack (assuming it can SEE the player when it attempts to do so).
So range does indeed make attacks increasingly rarer, but never with a zero chance. In order to do that you would need a value of dist >255 which would give a 256/256 cancellation chance, but would normally be impossible to achieve unless the distance calculations in P_ApproxDistance can cause some sort of overflow that would get past the capping. Setting it artificially to 256 makes indeed all monsters non-firing at ANY range, unless provoked (and then, they only fire once per provokation). Setting dist to 0 or negative removes all restraints on monsters, and they fire much more frequently.
AFTER an attack has been initiated, it might fail for other reasons (e.g. hitscan attacks actually ARE limited a-posteriori, archviles will abort if they lose LOS with their target), but the a priori causes are much more complex and unpredictable than people think, and luck/target behavior has far more influence than range.
Last edited by Maes on Oct 26 2011 at 17:05