• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Calculating a flying unit's flyheight

Status
Not open for further replies.
Level 6
Joined
Jun 18, 2004
Messages
119
Introduction:

Depending on the movement type of a unit, the pathing can be different. For instance, flying units can fly over ground blockers and "foot" units can walk over fly blockers. This behavior can be exploited in different situations. However, changing a unit's movement type also leads to differences in other behavior.

For example, flying units have a "natural flyheight", that is, without the user setting it's flyheight by object editor or triggers, the unit will automatically change its flyheight depending on the surrounding terrain. This basically means that units with the movement type "flying" cannot be used if one wants absolute control of the unit's flyheight, because there is a lack of the function "GetUnitAbsoluteFlyheight", or something similar (the function GetUnitFlyheight will not return the added flyheight by surrounding terrain). To be clear: I am not talking about the fact that you should subtract GetLocationZ from the flyheight to get the absolute height, I am well aware of this. However, as will be illustrated below, the height of the surrounding (that is, not only the one directly below the unit) influences its height.

Therefore, we must "reverse engineer" the method blizzard uses to add flyheight to flying units.

Method:


The method consists of creating a grid of flying units (with a flyheight of 0, I used makura missile as model) over terrain which has been altered. Then, a unit with "foot" movement type is placed at the same place, and 'Amrf' is added and remove to allow manipulation of its flyheight. It's flyheight is then altered by triggering (for example, a unit input command can set its flyheight) and it is visually checked to be of the same height. The process is repeated for different locations to find a formula that fits. For the purpose of clarity, I will refer to the added natural flyheight of the unit with flying movement type as the "z".

Results:

From the beginning, it was clear that the position of the "mountain" (that is, a place with raised terrain) is important. Terrain can be raised at a grid of 128, but if the gridpoint is "even" (that is, 0, 256, 512, etc) it seems to increase the z of the "odd" (that is, 128,384, etc) gridpoints around it, see Figure 1. I thus assumed that even though terrain can be raised at 128 gridpoints, the process that adds z is calculated based on a 256 grid.


evenGP.jpg
oddGP.jpg

Because of this reason, I began to only raise the odd gridpoints in order to make life easier. The odd gridpoint seemed to raise the z of surround terrain on the x-axis up to a distance of 512 in a straight line. Otherwise said (as we assumed a 256 grid), it raises the z of the gridpoints that are a distance of 256 away to 1/2 the height of the mountain. It behaves exactly the same in the y direction. Pretty straightforward so far.

Now, let's build a grid around this mountain, and try to calculate the flyheight gridpoints. As expected, the mountain influences the z around it in both the x and y direction, but also when x and y are both not 0, that is, diagonally the z is also raised (see Figure 2).


1mountain.jpg

the formula for 1 mountain is thus pretty straightforward. gridpoints at 256 away in 1 direction are raised by 1/2 the height of the mountain, gridpoints at 256 away in both directions (diagonally) are raised by 1/4 the height of the mountain. This calculation was perform, and the z of gridpoints indeed got raised correctly (see the bloodmage missile units in Figure 2). I then added a second mountain a distance of 512 away of the same height to see what would happen. As I hoped, the calculations worked flawlessly. I expected a "bridge" to form between the two mountains as (1/2)*h+(1/2)*h = h. This was indeed the situation as depicted in Figure 3, left.


2mountain512apart.jpg
2mountain256apart.jpg

Problems started to rise when the mountains started to be in the range of the other mountain, as depicted in Figure 3, right. As according to our formula the z of a terrainpoint is raised by 1/2*h by a mountain 256 away in one direction, and by 1/4*h by a mountain 256 away in both directions, we expected the points marked in red to be higher. However, this seems to not be the case. My code at that moment was the following:
JASS:
    set i = 0
    set r = 0.
    //perform a loop to get the surrounding heights of the terrain, and fill array h[] from 0 to 8 (0 = left bottom, 8 = right top, filled horizontally)
    loop
        set rel_y = (i/3)-1
        set rel_x = (i-(i/3)*3)-1
        set h[i] = .getZ(x+rel_x*2,y+rel_y*2)
        set i = i + 1
        exitwhen i > 8
    endloop
    // set the z to the origin (point 4)
    set z = h[4]
    // loop through the gridPoints 256 away in 1 direction and add their height difference between them and the origin / 2
    set i = 1
    loop
        if h[i] > h[4] then
            set z = z + (h[i]-h[4])/2
        endif
        set i = i + 2
        exitwhen i > 7
    endloop
    // loop through the gridPoints 256 away in both directions and add their height difference between them and the origin / 2
    set i = 0
    loop
        if h[i] > h[4] then
            set z = z + (h[i]-h[4])/4
        endif
        set i = i + 2
        exitwhen i > 8
    endloop
    // display the calculated z
    call .addZ(x,y,z)
In view of future problems with even gridpoints, I am calculating this based on a 128 spaced grid, thus, flyheight gridpoints are spaced 2 apart. The function .getZ returns the GetLocationZ of the real position of the gridpoint, and the function .addZ adds the z to the gridpoint's unit at the real position of the gridpoint.

Obviously, two connected mountains will lead to problems, but how do we sort this? There has to be an order of importance to the increasing of z. To try and find the logic here we test various scenarios. The first two are shown in Figure 3, the third scenario is depicted in Figure 4.


2mountainsdiagonal.jpg

The algorithm appearantly differentiates both axis in some way. From the observations we can deduct that: if the two mountains are on the same axis, they both contribute half their height to z to form a bridge. If the axis is different, however, it is less. I therefore used the following code:

JASS:
    if RMaxBJ(h[1],h[7]) > RMaxBJ(h[3],h[5]) then // blizz uses the highest mountain as preference.
        set z = z + (RMaxBJ(h[3]-z,0.)+RMaxBJ(h[5]-z,0.))/2
        set z = z + (RMaxBJ(h[1]-z,0.)+RMaxBJ(h[7]-z,0.))/2
    else
        set z = z + (RMaxBJ(h[1]-z,0.)+RMaxBJ(h[7]-z,0.))/2
        set z = z + (RMaxBJ(h[3]-z,0.)+RMaxBJ(h[5]-z,0.))/2
    endif

    // replacing:
    //set i = 1
    //loop
    //    if h[i] > h[4] then
    //        set z = z + (h[i]-h[4])/2
    //    endif
    //    set i = i + 2
    //    exitwhen i > 7
    //endloop

By doing so, the smaller mountain contributes less to the height if the axis are different, because it takes the z added of the previously added mountain in consideration. This seems to be correct, as illustrated in Figure 5.


correct.jpg

The algorithm now correctly deals with the error in Figure 4, but the error in Figure 3,right is still present. This is because the corner mountains influence the added z depending on nearby "side" mountains. Once this is taken into consideration, the algorithm works at odd gridpoints perfectly, as depicted in Figure 6. The code for this is shown below:

JASS:
// do the corners
set i = 0
loop
    set r = 0.
    // depending on the current position, get the highest "side" mountain
    if i == 0 then
        set r = RMaxBJ(h[1],h[3])
    elseif i == 2 then
        set r = RMaxBJ(h[1],h[5])
    elseif i == 6 then
        set r = RMaxBJ(h[3],h[7])
    elseif i == 8 then
        set r = RMaxBJ(h[7],h[5])
    endif
    if h[i] > r and h[4] < h[i] and i != 4 then
        set z = z + ((h[i]-RMaxBJ(h[4],r))/4) // calculate based on the highest point, either that at the origin, or of the side-mountain
    endif
    set i = i + 2
    exitwhen i > 8
endloop 
//replacing
//set i = 0
//loop
//    if h[i] > h[4] then
//        set z = z + (h[i]-h[4])/4
//    endif
//    set i = i + 2
//    exitwhen i > 8
//endloop


oddGP done.jpg

The only thing left afterwards is to integrate the even gridpoints. They behave in a funny way: the height of the center mountain (that is, h[4]) is increased by all surrounding even gridpoints, and the height of the side-mountains (that is, h[1,3,5,7]) is increased by the surrounding gridpoints perpendicular to the vector to the center. I don't know how I can explain this better. Anyway, the current code illustrated below works to define a FlyHeightGrid, as can be seen in Figure 7.


done.jpg

Current code:

JASS:
set z = 0.
set i = 0
set r = 0.
//do the even points stuff. (search in 128 area the highest point and use that as height)
loop
    set rel_y = (i/3)-1
    set rel_x = (i-(i/3)*3)-1
    if i != 4 then // if it is not the center, simply set it to the height of the point
        set h[i] = .getZ(x+rel_x*2,y+rel_y*2)
        // the sidenodes are increased by surround even gridpoints!
        if rel_x == 0 then
            set r = RMaxBJ(.getZ(x-1,y+rel_y*2),.getZ(x+1,y+rel_y*2))
            if h[i] < r then
                set h[i] = r
            endif
        endif
        if rel_y == 0 then
            set r = RMaxBJ(.getZ(x+rel_x*2,y-1),.getZ(x+rel_x*2,y+1))
            if h[i] < r then
                set h[i] = r
            endif
        endif                                
    endif
    if .getZ(x+rel_x,y+rel_y) > h[4] then // for the center one [4] check the tiles surrounding it at 128 distances
        set h[4] = .getZ(x+rel_x,y+rel_y)
    endif
    set i = i + 1
    exitwhen i > 8
endloop
set z = h[4]
// do the sides
if RMaxBJ(h[1],h[7]) > RMaxBJ(h[3],h[5]) then
    set z = z + (RMaxBJ(h[3]-z,0.)+RMaxBJ(h[5]-z,0.))/2
    set z = z + (RMaxBJ(h[1]-z,0.)+RMaxBJ(h[7]-z,0.))/2
else
    set z = z + (RMaxBJ(h[1]-z,0.)+RMaxBJ(h[7]-z,0.))/2
    set z = z + (RMaxBJ(h[3]-z,0.)+RMaxBJ(h[5]-z,0.))/2
endif
// do the corners
set i = 0
loop
    set r = 0.
    // depending on the current position, get the highest "side" mountain
    if i == 0 then
        set r = RMaxBJ(h[1],h[3])
    elseif i == 2 then
        set r = RMaxBJ(h[1],h[5])
    elseif i == 6 then
        set r = RMaxBJ(h[3],h[7])
    elseif i == 8 then
        set r = RMaxBJ(h[7],h[5])
    endif
    if h[i] > r and h[4] < h[i] and i != 4 then
        set z = z + ((h[i]-RMaxBJ(h[4],r))/4) // calculate based on the highest point, either that at the origin, or of the side-mountain
    endif
    set i = i + 2
    exitwhen i > 8
endloop 
//
call .addZ(x,y,z)

Conclusion:

The flyheight that is automatically added on unit's with movement type "Fly" by the surrounding (that is, not only the terrain directly underneath) can be calculated with the above algorithm. Although not very elegant, it is the only way to do this. I will in the near future release a resource that can get a flying unit's added flyheight based on this algorithm.

Thanks,

iNfraNe
 
Last edited:
Level 22
Joined
Feb 6, 2014
Messages
2,466
Because you should read all of it. Well, no. Maybe just the introduction ;)

Stopped reading after this
because there is a lack of the function "GetUnitAbsoluteFlyheight", or something similar (the function GetUnitFlyheight will not return the added flyheight by surrounding terrain).
My first suggestion won't solve this?? GetLocationZ returns the height of a location based on the terrain ;)
 
Level 6
Joined
Jun 18, 2004
Messages
119
GetLocationZ gives the height of the points, yes, but not the "added" height of the unit.

If you click on a picture, you'll see. All the units with the makura model have a FlyHeight of 0. Yet they hover alot above the ground, simply because they have movement type "fly". That added height is what I want to calculate.

I edited the intro a bit to make the difference clear.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
You need to test with non-identical cliff heights and more placement patterns.

Either they have some kind of intelligent logic guiding it (eg special cases for certain terrain height differentials) or they use some kind of image processing blur. Chances are it is fairly simple once you know what it is.
 
Indeed, I saw that thread. As nazgul himself notes, though: the calculation of the grid values is different

Besides, I don't really understand his code :)
Yeah, he wrote that it's super complicated, but possible. He also suggests a way to find out the parameters. I'd definitely take a look in that if you want to go on with this project.

What I assume is that the flight map differs from the camera map in the way that it is always a positive offset. This is to prevent units with a fly-height of 0 to clip through the ground. For the camera, the map is smoothed equally to negative and positive offsets. On flying units, that would look weird.


But there is also a big problem flying units in general:
Flying units will "tilt" when flying near a cliff. They are not always offset in parallel with the coordinate z-axis but can actually be off-axis. Good luck if you want to account for that aswell... I recommend ignoring that and require users to set maximum tilt angle to 0.
 
Level 6
Joined
Jun 18, 2004
Messages
119
You need to test with non-identical cliff heights and more placement patterns.

Either they have some kind of intelligent logic guiding it (eg special cases for certain terrain height differentials) or they use some kind of image processing blur. Chances are it is fairly simple once you know what it is.

I've indeed been doing so. I expect it to be fairly simple, which is whenever I need a lot of if/then/else in the code I feel that I'm on the wrong path. Could you elaborate a bit on what you mean by image processing blur? This could very well be the algorithm I'm looking for.

Zwiebelchen said:
But there is also a big problem flying units in general:
Flying units will "tilt" when flying near a cliff. They are not always offset in parallel with the coordinate z-axis but can actually be off-axis. Good luck if you want to account for that aswell... I recommend ignoring that and require users to set maximum tilt angle to 0.
This I don't find that much of a problem. Just setting it to 0 will not be a big hindrance.

Also: updated the first post. Getting closer.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Could you elaborate a bit on what you mean by image processing blur? This could very well be the algorithm I'm looking for.
There are dozen of algorithms used to blur images. They might be using one of them. They are usually the result of convoluting the image with some square filtering template which is an odd number of pixels wide (eg 3 or 5).
 
Level 6
Joined
Jun 18, 2004
Messages
119
I'm really not familiar with these algorithms. I might have just recreated one from scratch for all I know.

Either way, I worked it out. Took me some hours. See the first post (I realize this might be completely unreadable by this point :) ).

Thanks for thinking a bit about this with me, everyone!
 
I'm really not familiar with these algorithms. I might have just recreated one from scratch for all I know.

Either way, I worked it out. Took me some hours. See the first post (I realize this might be completely unreadable by this point :) ).

Thanks for thinking a bit about this with me, everyone!
Congratz for "cracking the code"!

Now present this in form of a neat library and upload it to the masses for collective praise. ;)
 
Level 6
Joined
Jun 18, 2004
Messages
119
Of course a lot can be optimized still, which I will do when making the resource. I'm atm still trying to include destructables. It would've been lovely if blizzard had used the same algorithm on those as on the terrain, but sadly... nope. They behave different, again. This is gonna take me a long time :'(

The destructables are even not symmetrical, see figure 1. It influences the z at positive x and y distance in a different way than the negative x and y (which appear to behave more or less like normal terrain).


stupid destructables.jpg

I made a table that shows the multiplication values needed for a destructable at x/y distances, see figure 2.


1 destructable table.jpg

When multiple destructables are present, the same kind of rules apply as with terrain. However, there are much more possibilities. I could use some help with the following. As can be seen in figure 3, gridpoints will sometimes be calculated wrong if more than 1 destructable is present.

-If the gridpoint is in between two destructables, the calculated value is too low
-If the gridpoint is beside two destructables, the calculated value is too high

The way I calculate the z is as following:
- loop through the destructables and sort them in height from low to high
- after the ordering is complete, loop through the sorted destructables and do:
set z = z + zfactor*(destHeight-z)
where z is the final z, zfactor is taken from the table as depicted in figure 2 and destHeight is the FlyOverHeight of the destructable.

This works flawlessly with 1 destructable, or if the destructables are "far enough apart (and on the same side of the gridpoint)" as is shown in Figure 3, left for the green circled gridpoints. For the red circled gridpoint in Figure 3, left, the formula should rather be:
set z = z + zfactor*(destHeight) //not taking into account the z added by previously checked destructables
The problem persists even if the destructables are opposite of the gridpoint, but very far away, as shown in Figure 3, middle.

Besides this problem, another problem can occur if there are 2 close destructables on the same side of the gridpoint, as shown in Figure 3, right. Here, the calculation turns out too high. In this case, the added z by the destructable further away should be ignored.


pic1.jpg
pic2.jpgpic3.jpg

The problem is: I cannot figure out what the rules here are... Does anyone have a clearer idea of whats going on?
 
Last edited:
Have you considered that the movement direction or facing of the flying unit might matter for destructables? Could explain why there is a difference between positive and negative X values if your dummy is facing to 0° degrees (in other words: pointed in +x direction).

Second idea that you might want to check before going on a witch-hunt with your calculus: Maybe the collision sphere/extents of your model matters? In that case, you are pretty screwed as there is no way to get that through triggers. So you might aswell rule that out first.


I just wanted to throw this into the discussion to remind you that you should test your calculations with other models/OE settings aswell just to go sure that these properties don't matter.
 
Level 6
Joined
Jun 18, 2004
Messages
119
Thanks for thinking along. Just tested these things (good idea on the facing angle!), but none seem to have an effect, either for the destructable, or for the unit (luckily, I suppose).

I'm still trying to decipher when my calculations are correct, and when they fail... it's difficult! :)

And after this I have to even combine destructables and terrain, which is also gonna be a pain!
 
I still try to find some logical explanation as to why the correctional factors in X and Y direction would be different. The only one I could come up with would be that maybe the internal algorithm uses even numbers for grid separation (which means that any median value has to be rounded up to get a whole number) instead of uneven numbers (which always has a whole number median). Which means that in a collection of tiles, a tile is never "centered" where you would expect, but actually on the bottom left corner of each cell.

Also, just look at your table again... now interpolate values each 32 coordinate units instead of 64 coordinate units...
suddenly, your data set looks symmetric, centered around the coordinate {-16;-16}:

... coincidently, the minimum possible grid in WC3 is 32x32 coordinate units (that is what units use), not 64x64 coordinate units. What if the system does not check the actual position of the unit, but just the 32x32 cell the unit is on? The center of each 32x32 cell would be at a 16x16 offset of the cell boundaries. If you place your testing dummy at map coordinate {0,0}, less than or equal checks would place it into the cell that has the diagonal corner points of: {-32,-32} to {0,0}. And the center of this cell is exactly at {-16,-16}.

I made a picture to show you what I mean. On the right side, the 0.875 value was interpolated and the left side value for 160 is an asumption by me based on the fact that both sides have the same slope (0.25 per 64 coordinate units). If I am correct, determining the values in steps of 32 coordinate units instead of 64 will prove my theory.


This also makes A LOT of sense from a programming perspective. I could imagine WC3 calculating the flight map as a per-pixel image at 1:32 resolution, just like they did with the pathing map.
The reason why cliffs and height modifiers are calculated differently is simple: unlike collision, the terrain height map uses a larger grid (64x64 instead of 32x32), so the extra resolution would just result in higher processing time with no increase in precision.
 

Attachments

  • symmetric.jpg
    symmetric.jpg
    29.8 KB · Views: 187
Last edited:
Level 6
Joined
Jun 18, 2004
Messages
119
Yes, I realized this. However, this is not the case for terrain, it is a destructable thing only. Terrain is perfectly symmetrical around the unit. Thus: there's something odd going on with the destructable calculations only.

What works is to add 16 to the destructable's position (both x and y), and calculate the distance from there. The distance to the unit, however, is calculated by a 64 grid. Which means: destructables that have a 64x64 place (for example, a canopy tree), will have a center that's not divisible by 64. In this case, the distance is rounded UP to the next 64 grid. This is the code that seems to define properly any destructable, when alone:

JASS:
            // set the destructable to a 64 grid. If it is centered on 32 (i.e., if it is a "small" destructable) then the distance is rounded up.
            set d = I2R(R2I(GetDestructableX(GetEnumDestructable())-.x)/64)*64.+16.
            set mod = (GetDestructableX(GetEnumDestructable())-.x)+16.-d
            set dx = d+mod*2
            set d = I2R(R2I(GetDestructableY(GetEnumDestructable())-.y)/64)*64.+16.
            set mod = (GetDestructableY(GetEnumDestructable())-.y)+16.-d
            set dy = d+mod*2
            // get the zfactor (these numbers are experimentally verified, the addition of 16 to the x and y secures a symmetrical grid)
            if RAbsBJ(dx) > 144. then
                set zfactor = zfactor * (1-(RMinBJ(RAbsBJ(dx),400.)-144.)/256.)
            endif
            if RAbsBJ(dy) > 144. then
                set zfactor = zfactor * (1-(RMinBJ(RAbsBJ(dy),400.)-144.)/256.)
            endif

However, the case where 2 destructables interact is still very difficult to decipher :)
 
That it's different for destructables and terrain makes a lot of sense, considering that destructables extend widgets (and units who also extend widget are calculated on a 32x32 grid size), but the minimum size of a destructable is 64x64.

Well, but at least that only leaves the interaction of two destructables left to decipher.
 
Level 6
Joined
Jun 18, 2004
Messages
119
"only" that, yes :)

logic.jpg

In the figure I show a simplified version (assuming symmetry around 0,0) of the destructable interaction, which I can't figure out how to program. The destructables are labeled black. I'm showing a 128grid here.

let's say this:
-for 1 destructable, the square 2 away is 1/2 the height of the dest
-once a destructable is added "on the same side", it does not add to the height
-if it is on the side, it adds to the height like: z=z+(destz-z)/2
-if it is on the opposite side, it adds to the height like: z=z+destz/2

if someone can think of logical way to calculate this, without a million if/then/elses, I'd really like to know!

edit:

some combinations and their added Z... hard to figure out...
realnumbers.jpg
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
A lookup table of sorts could trade efficiency for code neatness to do all the "million if/then/elses".

You might also want to reverse engineer that part of the game logic. Although technically a ToU violation you are not using it for malicious purposes and still inside the game so most people should be happy with it.

It is highly likely some image processing algorithms or logic are being used. Anomalies present might be the result of how the algorithm works or even rounding error.
 
Level 6
Joined
Jun 18, 2004
Messages
119
You might also want to reverse engineer that part of the game logic. Although technically a ToU violation you are not using it for malicious purposes and still inside the game so most people should be happy with it.

It is highly likely some image processing algorithms or logic are being used. Anomalies present might be the result of how the algorithm works or even rounding error.

I'm quite interested in this, but have no idea how to go about doing that. Do you have any idea?
 
That is ... horrible. Why would blizzard do such inconsequent shit?

Did you take the issues we found above with the actual calculation center being different than the geometric center into account? And the difference between grid coordinates and cells?

Because all this table data will look skewed and weird if we already misjudge the origin of our coordinate system.


My guts tell me it is this problem again, just in a different color:

149448d1445343500-calculating-flying-units-flyheight-symmetric.jpg
 
Level 6
Joined
Jun 18, 2004
Messages
119
You just have to think the origin up 16 in both directions. I can't place the destructables differently than on the 64grid, so the reality is that it will look weird always. This is one of the problems I'm having finding a formula.. the numbers just seem random (for instance, when I see 0.390625, I don't think "ah, thats 25/64!).

I've got an excel document with some experimental data, but sadly hive doesnt let me attach it. The good part is: I've never found a single case where the height is not on this formula:
(i/64)*h, where i is an integer. This probably means that the calculation consists of additions of multiplications of x/8 fractions. This makes sense, as for one destructable the formula is:
set z(x,y)=(1-RMaxBJ((dx-144)/256.1)*(1-RMaxBJ((dy-144)/256,1)*h (h = destructable flyover height, dx and dy are the "real" distances to the dest taking into account the +16), which will always lead to a fraction of 64.

This also means that the final formula cannot contain much more than just additions and substractions of such terms, as otherwise the fraction wouldnt work anymore. Based on this, I have designed the following puzzle for you guys to solve (because I, for the life of me, can't find the link):



5
4

4
5
= 39




5
5

4
4
= 40




5
4

6
5
= 47




3
8

4
8
= 56




3
6

4
8
= 50




3
7

4
8
= 53




3
5

4
8
= 47




5
5

4
8
= 52




5
7

4
8
= 60


It's puzzling time! (so, the numbers in the matrix are /8 and the answer is /64. I found this the most logical representation, if you don't agree, let me know what would be a simpler way to tackle the problem.
 
You still calculate destructables as if the minimum grid size is 64x64...

Just because the smallest default pathing texture is 64x64 that doesn't mean that a 64x64 grid is the right asumption.

Actually, the pathing texture of a 64x64 destructable (like an ashenvale tree) is called "2x2" and a guard tower or lordaeron tree pathing texture is called "4x4". Which makes me assume that even an ashenvale tree is actually calculated as a set of 4 32x32 cells individually.

What if the pathing texture matters for fly height? After all, there are non-rectangular pathing maps.


Here is what I assume: the formula you made actually applies in case of multiple destructables (and all factors get summed until the total is 1), however, every 64x64 destructable is actually split in 4 seperate 32x32 calculations.

That would explain why shape 2 and shape 3 in the top row of your table, despite being perfectly point-symmetrical yield slightly different values (as we offset by 16x16).
 
You're completely spot on. The pathing map size matters. That's just superlovely. In that case, I guess we could call this impossible?
Only if you use non-rectangular destructables.


To be honest, at this point I'd just tell the user not to use "overfly height" at all and go with your terrain-only calculus.
What could this probably be useful for anyway? Missile systems? I don't think accuracy even matters there, as it's just a for visual purposes anyway (GetLocationZ() is asynchronous).

And if people want to make a flight-simulator, they have no use for "overfly height" anyway, as crashing your plane into the terrain would be kind of a gameplay element.
 
Level 6
Joined
Jun 18, 2004
Messages
119
It could potentially be useful for any map that uses flying units together with a missile system. Or to differentiate between units with different pathing. Either way, a nice way to actually get the flyheight of the unit is something that should be available, I feel.

I myself have never ever had any problems with GetLocationZ causing desyncs. It has been employed in Elimination Tournament for years, without ever causing trouble.
 
It could potentially be useful for any map that uses flying units together with a missile system. Or to differentiate between units with different pathing. Either way, a nice way to actually get the flyheight of the unit is something that should be available, I feel.

I myself have never ever had any problems with GetLocationZ causing desyncs. It has been employed in Elimination Tournament for years, without ever causing trouble.
It doesn't cause trouble if it is only used to change the unit's flyheight. It does however get you in trouble as soon as you actually use it to determine "real" z-collision.
 
Level 6
Joined
Jun 18, 2004
Messages
119
Could you link me to a thread proving this?

I do exactly that, i.e., if unit height < getlocz then I kill the unit, or if it hits another unit within a z range, kill it. All sorts of stuff, without desyncs.
 
Could you link me to a thread proving this?

I do exactly that, i.e., if unit height < getlocz then I kill the unit, or if it hits another unit within a z range, kill it. All sorts of stuff, without desyncs.
The problem is that GetLocationZ() will adapt to walkable destructables. And these destructables have a variable render state, depending on the camera position of the user.

You can actually try that out on your own if you don't believe me: place a walkable floating ice destructable somewhere on the map, then place a unit on top.
Have a trigger that periodically displays GetLocationZ(), then move the camera around.
You will notice that GetLocationZ() will eventually go back to 0.

But it's even worse than that: as animations are not synchronous, any type of floating walkable platform that moves when animated will cause asynchronous GetLocationZ() reads.

GetLocationZ() should never be used for collision, only for changing FlyHeight (which has no impact on gameplay and is purely visual).
 
Level 6
Joined
Jun 18, 2004
Messages
119
The problem is that GetLocationZ() will adapt to walkable destructables. And these destructables have a variable render state, depending on the camera position of the user.


You can actually try that out on your own if you don't believe me: place a walkable floating ice destructable somewhere on the map, then place a unit on top.
Have a trigger that periodically displays GetLocationZ(), then move the camera around.
You will notice that GetLocationZ() will eventually go back to 0.
I have been unable to confirm this. The GetLocationZ outputs the same whereever I move my camera around a walkable rock. Up to distances of >10000 away, rotated, whatever. Same for the ice floe, but that of course has an animated value. Which bring me to your next point.
But it's even worse than that: as animations are not synchronous, any type of floating walkable platform that moves when animated will cause asynchronous GetLocationZ() reads.
This is not that big a deal, simply don't use animated destructables that are walkable...
GetLocationZ() should never be used for collision, only for changing FlyHeight (which has no impact on gameplay and is purely visual).
Again, you're annihilating entire genres of maps here for no reason. As long as people know what they are doing, and don't change terrainheight locally (by whatever method including animated walkable destructables), it seems to be safe in my book. Even in the worst case scenario, when people can't use destructables, terrain deforms or spells that deform terrain, it is still a huge asset to the mapmaker which can, and should, be used.
 
Neither then does it cause any problems. I'll believe you once you send me a map that gives inconsistent results ;) until then, I'm very happy with my GetLocationZ
If you are willing to risk it, no objections. Just saying that this is something you should consider, especially the animation thing.
 
Status
Not open for further replies.
Top