HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

How is there a desync?

04-02-2010, 02:12 PM#1
Tastingo
I cannot figure out why everyone is desyncing. This function used to work till I added the variables camSet[] and playerCam to it. I have looked over it more than I think 20 times. I still cannot figure it out, and was wondering if maybe someone would take a look at it for me and figure out why their is a desync. It happens right at the beginning of the game, and this was one of the only things I changed.

The function is ran by a timer every .03 seconds. It loops through all the players and if they are playing and not dead locks the camera to their unit. If they die it originally locks the camera to an ally. They can change the camera with the left and right arrow keys in another function, and doing so locks it to one of them.

Globals:
playing[] is if the player is playing
isDead[] is if the unit is dead
playerCam[] holds the player number currently the camera is locked too. (Arrow key functions change it, for last part of this function)
camSet[] is if the player changed their target with left and right arrow keys.

Any help would be extremely useful :).

Collapse JASS:
function timerCameras takes nothing returns nothing
   local integer i = 0
   
    //! textmacro Camera takes PlayerNum
    call SetCameraTargetController(players[$PlayerNum$], 0, 0, false)
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 250.00, 0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 185.00, 0)
    call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, 100.00, 0)
    call SetCameraField(CAMERA_FIELD_ROLL, 180.00, 0)
    call SetCameraField(CAMERA_FIELD_ZOFFSET, 120.00, 0)
    call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(players[$PlayerNum$]) + 180, .18)
    call SetCameraField(CAMERA_FIELD_FARZ, 2500, 0)
    //! endtextmacro

    
    loop
        if playing[i] == true then  //Check if playing
            if isDead[i] == false then  //Keep camera on living target
                set playerCam[i] = i
                if GetLocalPlayer() == Player(i) then
                    //! runtextmacro Camera("i")
                endif
            else //Swap camera to living person
                if camSet[i] == false then  //Check if they move their own camera
                    if i < 4 then   //On Team 1
                            if isDead[0] == false then
                                set playerCam[i] = 0
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("0")
                                endif
                            elseif isDead[1] == false then  //Change dead player camera to Blue
                                set playerCam[i] = 1
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("1")
                                endif
                            elseif isDead[2] == false then  //Change dead player camera to Teal
                                set playerCam[i] = 2
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("2")
                                endif
                            elseif isDead[3] == false then  //Change dead player camera to Purple
                                set playerCam[i] = 3
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("3")
                                endif
                            endif
                    else    //On Team 2
                            if isDead[4] == false then  //Change dead player camera to Yellow
                                set playerCam[i] = 4
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("4")
                                endif
                            elseif isDead[5] == false then  //Change dead player camera to Orange
                                set playerCam[i] = 5
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("5")
                                endif
                            elseif isDead[6] == false then  //Change dead player camera to Green
                                set playerCam[i] = 6
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("6")
                                endif
                            elseif isDead[7] == false then  //Change dead player camera to Pink
                                set playerCam[i] = 7
                                if GetLocalPlayer() == Player(i) then
                                    //! runtextmacro Camera("7")
                                endif
                            endif
                    endif
                else    //If they set their cam with arrow keys
                    if(GetLocalPlayer() == Player(i)) then  //Change camera for local player only
                        //! runtextmacro Camera("playerCam[i]")
                    endif
                endif
            endif
        endif
        set i = i + 1
        exitwhen i > 7
    endloop
endfunction
04-02-2010, 04:58 PM#2
Troll-Brain
Are you sure it comes from directly this function, and not a consequence, for example in an other function you use camera target X/Y to create/destroy handles/open a new thread, what ever else which cause a desync.

AFAIK you don't have any desync stuff in it.

You could even do that :

Collapse JASS:
function timerCameras takes nothing returns nothing
   local integer i = GetPlayerId(GetLocalPlayer())
   
    //! textmacro Camera takes PlayerNum
    call SetCameraTargetController(Player($PlayerNum$), 0, 0, false)
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 250.00, 0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 185.00, 0)
    call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, 100.00, 0)
    call SetCameraField(CAMERA_FIELD_ROLL, 180.00, 0)
    call SetCameraField(CAMERA_FIELD_ZOFFSET, 120.00, 0)
    call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(players[$PlayerNum$]) + 180, .18)
    call SetCameraField(CAMERA_FIELD_FARZ, 2500, 0)
    //! endtextmacro

    
        if playing[i] then  //Check if playing
        
            if isDead[i] == false then  //Keep camera on living target
                set playerCam[i] = i
                //! runtextmacro Camera("i")

            else //Swap camera to living person
            
                if camSet[i] == false then  //Check if they move their own camera
                
                    if i < 4 then   //On Team 1
                    
                        if isDead[0] == false then
                            set playerCam[i] = 0
                        
                            if i == 0 then
                                //! runtextmacro Camera("0")
                            endif
                        
                        elseif isDead[1] == false then  //Change dead player camera to Blue
                            set playerCam[i] = 1
                        
                            if i == 1 then
                                //! runtextmacro Camera("1")
                            endif
                        
                        elseif isDead[2] == false then  //Change dead player camera to Teal
                            set playerCam[i] = 2
                        
                            if i == 2 then
                                //! runtextmacro Camera("2")
                            endif
                        
                        elseif isDead[3] == false then  //Change dead player camera to Purple
                            set playerCam[i] = 3
                        
                            if i == 3 then
                                //! runtextmacro Camera("3")
                            endif
                        
                    else //On Team 2
                    
                        if isDead[4] == false then  //Change dead player camera to Yellow
                            set playerCam[i] = 4
                            
                            if i == 4 then
                                //! runtextmacro Camera("4")
                            endif
                            
                        elseif isDead[5] == false then  //Change dead player camera to Orange
                            set playerCam[i] = 5
                            
                                if i == 5 then
                                    //! runtextmacro Camera("5")
                                endif
                                
                        elseif isDead[6] == false then  //Change dead player camera to Green
                            set playerCam[i] = 6
                            
                                if i == 6 then
                                    //! runtextmacro Camera("6")
                                endif
                                
                        elseif isDead[7] == false then  //Change dead player camera to Pink
                            set playerCam[i] = 7
                            
                            if i == 7 then
                                //! runtextmacro Camera("7")
                            endif
                            
                        endif
                    
                else    //If they set their cam with arrow keys
                    //Change camera for local player only
                    //! runtextmacro Camera("playerCam[i]")

                endif
            endif
        endif

endfunction

if camSet[i] == false == if not camSet[i] and
if camSet[i] == true == if camSet[i]
On an other note i consider this if/elseif block as overkilled you could really make your code shorter with (very) negligible performance loss.
04-03-2010, 03:28 AM#3
Tastingo
Nah I just use it to set the cameras. The other functions set the variables though, if that helped answer your question. I don't use like GetCameraX or whatever :). I tested it again with 2 people instead of a full house and it didn't desync which was weird. I think I heard someone said there are bugs with macs and cameras, maybe that could be it? Not really sure, or maybe just the bot that hosted the game.
04-04-2010, 12:14 AM#4
Opossum
I don't think this function is causing it. Every time you use GetLocalPlayer() you are only using that text macro which only contains camera changes i.e., local functions.
Camera changes alone can't cause desyncs. Even if they are taking desynced arguments.
Actually everything this function contains is desync-safe. 'If's don't care if they get desynced conditions. Setting variables locally isn't an issue either as long as you're keeping them locally.
Quote:
I tested it again with 2 people instead of a full house and it didn't desync which was weird.
As this is a periodic function which runs from the beginning (I assume?) it really can't be the issue. Maybe it was one of the keyboard functions which none of you two were using.

Check your other functions for GetLocalPlayer blocks and watch out for variable settings and function calls. Variable settings won't desync the game instantly but they will once they are used in a global function.

Apart from that... what happens if a player changes his target using arrow keys to let's say Blue and then Blue dies? You'd end up in the 'else' section of if camSet[i] == false then which doesn't check if Player(playerCam[i]) is still alive so the camera will target a dead unit.

oh and @Troll-Brain: You don't wanna take out those local blocks unless you want to screw up the camera totally for all players. Using local functions like those camera functions in global code will apply these settings to ALL players which would result in a total mess in this case.

Some other points:

You can take all those lines out of the textmacro. They run always anyway:
Collapse JASS:
    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 250.00, 0)
    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 185.00, 0)
    call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, 100.00, 0)
    call SetCameraField(CAMERA_FIELD_ROLL, 180.00, 0)
    call SetCameraField(CAMERA_FIELD_ZOFFSET, 120.00, 0)
    call SetCameraField(CAMERA_FIELD_FARZ, 2500, 0)
If you use local functions like this in global code they're simply applied to all players so you can just as well put them at the beginning of your function.

Also you should maybe use a second loop for the camSet[i] == false case. Currently this looks so like a GUI code :).


And yeah... might I recommend this system? Some really awesome guy made this a while ago and seeing you're doing some sort of 3rd person cam too you might find it useful. All you'd have to do would be set up that "death cam" using a "UNIT_DEATH" trigger.
Edit: There I even gave it a quick try using OppiCam (not tested):
Expand JASS:
04-04-2010, 03:05 AM#5
Tastingo
I found out that the code was actually safe like you guys said. It was the bot. I had a few games of full houses and they worked fine.

To answer Opposum: When someone dies it changes the camera and the arrow keys switching between targets checks for death.

No its not GUI code lol, just a big coincidence lol.

Thank you for the help guys, even though I wasted your time :(.
04-04-2010, 09:58 AM#6
Troll-Brain
Quote:
oh and @Troll-Brain: You don't wanna take out those local blocks unless you want to screw up the camera totally for all players. Using local functions like those camera functions in global code will apply these settings to ALL players which would result in a total mess in this case.
Actually, i don't see why, sure it will be applied for all players, but his code itself do already.
Well, i assumed that the other players are computers or empty slot but not real players, if my guess was wrong then you are right.

EDIT : If i'm right, you also don't need some other arrays, just set the variables locally.