• 🏆 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!

Weird behaviour: GetLocationZ() does return incorrect value

Status
Not open for further replies.

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
I have a whole set of hidden destructables for different players.
In order to provide a synced Z detection no matter the visibility state of the destructable, I use this script to temporarily unhide all destructables in a given area.

Don't think about everything outside the innermost loop. It works.

Basicly, what doesn't work is the following:
In the innermost loop, the DebugMsg is displayed properly all the time (9 times in total, as expected). However, the z value returned is 0 although it should be higher (somewhere around 300).

What is even more strange is that sometimes it works, sometimes it doesn't.
No matter what: the "checked" message is ALWAYS displaying the expected behaviour. It's just the z value that is not properly get.

I'm totally confused. This does not make any sense to me!

JASS:
function GetLocationZSynced takes location l returns real
    local integer row = R2I((GetLocationY(l)-mapMinY)/TILESIZE)
    local integer column = R2I((GetLocationX(l)-mapMinX)/TILESIZE)
    local integer x1 = column-1
    local integer x2 = column+1
    local integer y1 = row-1
    local integer y2 = row+1
    local integer a
    local integer b
    local integer j
    local integer id
    local integer count
    local real z = GetLocationZ(l)
    local destructable d
    //border safety:
    if x1 < 0 then
        set x1 = 0
    elseif x2 >= columns then
        set x2 = columns-1
    endif
    if y1 < 0 then
        set y1 = 0
    elseif y2 >= rows then
        set y2 = rows-1
    endif
    set a = x1
    loop
        set b = y1
        exitwhen a > x2
        loop
            exitwhen b > y2
            set id = b*columns+a
            if not LoadBoolean(hash, id, -1) then //only check hidden squares
                set count = LoadInteger(hash, id, 0)
                set j = 0
                loop
                    exitwhen j >= count
                    set j = j + 1
                    set d = LoadDestructableHandle(hash, id, j)
                    call ShowDestructable(d, true)
                    set z = RMaxBJ(z, GetLocationZ(l))
                    call BJDebugMsg("checked")
                    call ShowDestructable(d, false)
                endloop
            endif
            set b = b + 1
        endloop
        set a = a + 1
    endloop
    set d = null
    return z
endfunction

Just to go sure, I checked the existance of d and all the GetLocationZ() values returned per loop iteration:

- When the destructables are currently shown by other means, the value returned is correct.
- The handles for d always exist (tested by debug message)
- When the destructables are hidden again, for 1 or 2 seconds the correct value is returned, after that, GetLocationZ() in the innermost loop just returns 0
- Even more weird: sometimes even after 2 seconds, the GetLocationZ() returns the correct value for an infinite amount of time.
 
Last edited by a moderator:
Level 26
Joined
Aug 18, 2009
Messages
4,097
Afaik GetLocationZ does depend on the render state, so fog of war/visibility through fog, camera position and model animation (which is async) play a role. Maybe it is not instantly rendered by the graphics engine.

Well, what is the use of half-sync walkable destructables in your scenario?

GetLocationZ is not really suited/thought for gameplay relevance.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Afaik GetLocationZ does depend on the render state, so fog of war/visibility through fog, camera position and model animation (which is async) play a role. Maybe it is not instantly rendered by the graphics engine.

Well, what is the use of half-sync walkable destructables in your scenario?

GetLocationZ is not really suited/thought for gameplay relevance.
To be honest, I never thought of the possibility that GetLocationZ() might be affected by fog of war or visibility. Now that you mention it this makes sense and I should definitely check that with a more simple script.

However, from my observations, GetLocationZ() only fails when the destructable was formerly hidden on my script. If it was shown before, it always returned the correct value (but it seems that the animation of the destructable stops, so that my vibrating floating test-platform suddenly returns static values).
Also, what is even more weird is, that the return value is dependant on the position of the camera. If I move the camera to the north of the destructable, GetLocationZ() returns 0.
If I move the camera to the southwest of the destructable, GetLocationZ() works fine.
If I move the camera to the east of the destructable, GetLocationZ() returns the correct value for a couple of seconds and then returns 0.

I just checked some missile systems using GetLocationZ() and I'm still not convince they would work flawlessly without properly synced Z data. But I think I'll check that again. If it's only for graphical stuff, this is no problem (good thing that UnitFlyHeight is not required to be synced), but as soon as it's used for collision detection, things might fail.

EDIT:
I did a test now with a simple EnumDestructablesInRect, showing destructables and printing the GetLocationZ() for a location placed on that destructable. It seems that there is indeed a connection to the render state of the destructable. Which basicly means GetLocationZ() is pretty much useless other than for visible stuff and theres no reason to code a GetLocationZSynced().
 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,192
GetLocationZ ignores destructible height as far as I am aware. This means a bridge across a river (typical melee type bridge) will show a sudden fall as it goes off the cliff and a rise when it gets to the other side.

Otherwise GetLocationZ could easily cause a de-synchronization if used on an animated walkable destructible like an abomination. Either that or it takes the initial animation state of the model.

Synchronizing Z data for a projectile system is not possible. If it does depend on walkable destructible animation state then you will need to make sure the model is always visible and no local animation is playing. Using an abomination as walkable would be out of the question.

A computationally intensive but feasible work around would be to create your own height map which includes readings for walkable destructibles that are synchronized. You then interpolate actual height from these points. Not as accurate but should avoid run time synchronization. If only JASS compiled to something faster than being interpreted.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
GetLocationZ ignores destructible height as far as I am aware. This means a bridge across a river (typical melee type bridge) will show a sudden fall as it goes off the cliff and a rise when it gets to the other side.

Otherwise GetLocationZ could easily cause a de-synchronization if used on an animated walkable destructible like an abomination. Either that or it takes the initial animation state of the model.

Synchronizing Z data for a projectile system is not possible. If it does depend on walkable destructible animation state then you will need to make sure the model is always visible and no local animation is playing. Using an abomination as walkable would be out of the question.

A computationally intensive but feasible work around would be to create your own height map which includes readings for walkable destructibles that are synchronized. You then interpolate actual height from these points. Not as accurate but should avoid run time synchronization. If only JASS compiled to something faster than being interpreted.
Thanks. So basicly making something like GetLocationZSynced() is out of question.
Saves me unneccessary work and a lot of trouble, which is a good thing. ;)

So, updated DestructableHider to v1.3. :)
 
Status
Not open for further replies.
Top