There’s no TL;DR I’m afraid. If you’re interested in this subject read on. I think it’ll be interesting for those that have an interest in creature movement and Z position issues.
I’ve been looking into this, since while testing the dynamic spawn changes I was levelling a warlock and found the minion to be falling through the floor far more than we should be accepting. In my initial investigation I came across something that I feel is obviously wrong and has been since the beginning of TC time.
https://github.com/r00ty-tc/TrinityCore/commit/10550fe8cff1fb91c8084b623fe243a6340ea52d
Now, this change fixes a lot of the cases this happens. The original code seems to be based on the premise that if the object’s z position is already under z then it’s a problem. Whether or not that’s true is actually irrelevant though. Since this function is more often than not used to find the floor Z in a position some distance from the starting position. Where often the selected position would be below ground but we want to follow the contour above. In my mind, in every case that matters we should be using map and vmap floor level and accept whichever is closest to our original Z.
Now, onto my next line of thinking. Quite often the system is fooled by a second layer of ground very close to the one we want. Best example for this is Sunstrider Isle. Where the mana wyrms are roaming on and off the platform. Often they fall through. The reason here is quite obvious. That the ground level continues under the platform. When moving from normal ground level to the position on the platform the floor Z that is closest to that original Z is the under floor level. The solution came from a discussion with Treeston on this issue. Where a good way to solve this, again not for all cases, but most is to use the mmap tile z position, where available. This lookup take a minuscule amount of time compared to a full path lookup (very much fraction of a ms, we could probably time it in microseconds or less). Using this floor Z as a basis then finding the floor from there (with the usual +2.0f) fixed things for most places.
However, again there’s some exceptions. In Deathholme (Ghostlands) for example there’s some places where mmap Z is 4-5 below the surface. Resolving this moved onto a new idea for resolving height.
The functions to derive true floor Z have a limitation, which is quite obvious when you think about wow textures. That is, for the floor you’ll only get a reliable hit looking down (since looking up you either have no texture, or worse you’ll hit the bottom of the platform not the top). So traditionally we look 2.0f above the Z we want and just hope there’s nothing higher than that. Except there is. Now, seeing as we have a good starting point (either previous position Z or mmap Z) rather than a fixed 2.0f. I think we should start searching both ways. So, look down from initial z (mmap or previous). Get first strike. Then look from +8,0f (so far I’ve not seen anything with this much difference). If the value is the same as the search from initial z. Then we search no more. If there is another value, we search from that point -1.0f until we reach the first search value or a better match (a z closer to the initial z). In this case, in most cases it’s one extra height call (rays are costly). Only where the detail is complex will more than 1 extra call be needed.
At this point we’ll have a very good getHeight function. If there’s situations where it returns bad Z values, it’s likely the movement generators checks for LoS will catch it anyway. If not, we need to look into LoS checking on the movement destination. This wouldn’t be nice but, it’s a next step if we still find problems.
After making the above changes, I found charge worked in ALL KIND of places it would usually fail. In fact, I simply couldn’t get charge to fail and I couldn’t make the minion fall underground. This is almost mission accomplished.
Then I tried fear on player. Now, in most cases where this used to fail I found it was resolved (Dalaran inside buildings etc). My thinking is that is was choosing a Z below ground and thus not seeing the walls from the perspective. I’m not sure what was really happening. But it seems to resolve them. The problem still arises where there is mountainous terrain. Here’s where I think things go wrong.
Fear, chooses a point in a random direct at a random distance (up to a specific limit). The problem is, the path finding finds paths for creatures and creature pathfinding seems to be accept paths where a player should not be able to run. My example area was The Supulcher. The mountains around there, it will let you path up to silly heights. Worse, the pathfinding is not set to straight line. So it will happily make a path AROUND the mountain. Except it seems that when feared it does not use that path, but rather goes direct (AKA through the mountain). There’s also a lot of weird animation that happens and I think it’s mainly because movements for a player are sent to the client, which the client plain and simply does not like. Not I tried this with charge, the charge pathed around the mountain correctly. Fear chose the same path and went through the mountain. I think it’s client overriding server given path. But I’ll need to debug actual packets to be sure of that.
I’m still investigating this area. But, the solution seems convoluted and I think would require more CPU. Hence it would need to be on a parameter. First change, path generation using straight line mode. Next change is that the path is already split into 10 steps. The checks on these 10 steps include a check on player climbable (45-50deg limit) on the mmap Z (not texture Z). Stopping at the point before that happens.
This resolves the problems most of the time. But, still some issues remain.
So, mainly this post is a bit of a result of my research in the area and maybe a chance for some people that have maybe been here before to point me away from any direction I’m going that is wasting time.