• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Does GetLocationZ() Cause Desyncs?

Status
Not open for further replies.
Level 4
Joined
Mar 3, 2010
Messages
68
I have a question for any JASS users out there. Does using GetLocationZ() cause occasional desyncs? I am asking because my map is suffering from occasional desync problems and I suspect this is due to the function GetLocationZ() since they do not happen once I remove all references to it.

The problem does not seem to happen consistently but if anyone knows what causes it, I'd love to know.

Here is what I am using:

JASS:
function HeightDamageCalculation takes unit Source, unit Target returns real
    
    local real D
    set udg_ZLoc = GetUnitLoc( Source )
    set D = GetLocationZ( udg_ZLoc )
    call RemoveLocation( udg_ZLoc )
    set udg_ZLoc = GetUnitLoc( Target )
    set D = D-GetLocationZ( udg_ZLoc )
    call RemoveLocation( udg_ZLoc )

return D
endfunction
 
Level 4
Joined
Mar 3, 2010
Messages
68
Ah thanks so much ^^, will use carrion swarm as a substitute.

Second question though, this desync problmem still seems to be plagueing me but I've noticed something strange. People who play the map twice in a row tend to desync whereas if I am a playing a fullhouse game with an entirely new set of people, there is never a desync. Any ideas?

edit: Talked to some of my map testers and they said that this seemed to be consistent. No problems first game, replaying the map again causes desyncs.

edit #2: narrowed down the problem even further, when the desync message pops up, all player who have previously played the map recently (without restarting client) are in game state #2, all those who are playing for the first time get split into game state #1. Is there anything that carries over between maps?
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,097
Wc3 was never a proper 3d game, which is why z height is async all the way.

A typical mistake is also when you have animated walkable destructables. Walkable destructables change the result of GetLocationZ and animations are not in sync, only rendered when player has view there etc.
 
Ah thanks so much ^^, will use carrion swarm as a substitute.

Second question though, this desync problmem still seems to be plagueing me but I've noticed something strange. People who play the map twice in a row tend to desync whereas if I am a playing a fullhouse game with an entirely new set of people, there is never a desync. Any ideas?

edit: Talked to some of my map testers and they said that this seemed to be consistent. No problems first game, replaying the map again causes desyncs.

edit #2: narrowed down the problem even further, when the desync message pops up, all player who have previously played the map recently (without restarting client) are in game state #2, all those who are playing for the first time get split into game state #1. Is there anything that carries over between maps?

My intuition tells me it's string leaks :3
Are you using GetLocalPlayer() ever?
If so, could you post /all/ your code that uses it?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
reminder from common.j:

JASS:
// This function is asynchronous. The values it returns are not guaranteed synchronous between each player.
//  If you attempt to use it in a synchronous manner, it may cause a desync.
native GetLocationZ             takes location whichLocation returns real
 
Level 4
Joined
Mar 3, 2010
Messages
68
Thanks for all the suggestions, I'll have to keep that height-map idea in mind.

My issue though, I suspect, may be something other than GetLocationZ(). After scouring the internet, I read that sounds persist in between maps. In my map, I increased the volume of a sound variable via trigger on initialization (to get it to play above 100%). I suspect that when a player plays the map twice, the volume of the sound is increased a second time from the originally increased volume sound whereas a player playing the map for the first time only has the volume sound increased once. Once the sound is played, the map desyncs into two groups. My map plays these increased volume lightning sounds at random intervals so that could explain why this bug was so hard to pin down.

  • Custom script: call SetSoundVolumeBJ( udg_Lightning_Sounds[3], 150 )
I'll post an update later on whether this was the issue. It should be a simple matter of exporting the sounds, opening them in audacity, increasing the volume and re-importing them back into the map.

--------

Regardless, I'm going to post all the JASS functions I have using getlocalplayer() anyways, but I'm pretty confident that they do not cause desyncs as I have used them many times successfully.

JASS:
function CinematicFadeForPlayer takes player p, real red, real green, real blue, real duration, string tex, real startTrans, real endTrans returns nothing
    if (GetLocalPlayer() != p) then
        return
    endif
    if (duration == 0) then
        set startTrans = endTrans
    endif
    call SetCineFilterTexture(tex)
    call SetCineFilterBlendMode(BLEND_MODE_BLEND)
    call SetCineFilterTexMapFlags(TEXMAP_FLAG_NONE)
    call SetCineFilterStartUV(0, 0, 1, 1)
    call SetCineFilterEndUV(0, 0, 1, 1)
    call SetCineFilterStartColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100-startTrans))
    call SetCineFilterEndColor(PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100-endTrans))
    call SetCineFilterDuration(duration)
    call DisplayCineFilter(true)
endfunction

JASS:
function PlaySoundForPlayer takes sound s, player p returns nothing
    set bj_lastPlayedSound = s
    if s != null and GetLocalPlayer() == p then
        call StartSound(s)
    endif
endfunction
I am aware that this should not be used for 3-D sounds.

JASS:
function ShowMultiboardForPlayer takes nothing returns nothing
    local integer i = 1
    call TriggerSleepAction( 0.00 )
    set i = 1
    loop
        exitwhen i > 12
        if ConvertedPlayer(i) == GetLocalPlayer() then
            call MultiboardDisplayBJ( true, udg_Multiboards[i] )
        endif
        set i = i + 1
    endloop
endfunction
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
So you still might consider a custom height map. Save all the values at the beginning of the game or write a tool that reads the .w3e from the map archive to convert it to jass code. If you have modifiers like terrain deformations or walkable destructables ingame, catch them during runtime and add them to height calculations.
The problem is the poor data structures that WC3 supports. For it to be done efficiently you would need to use a big array which acts as the height buffer.

For a 256*256 map (not XXL) it would need 2^16 indices. This translates to 8 arrays in series or a heavily loaded hashtable.

Still possible there but when you get to a 448*448 map...
That is 25 series arrays or 200704 entries.

Even if series arrays can be made to have an O(log(N)) complexity though a binary search it is still a big overhead if you want it to be done many times a second.
 
Status
Not open for further replies.
Top