HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Camera System Desync Problem

04-08-2010, 05:46 PM#1
deathreaper945
I've been working on this Camera System where you adjust the camera's angle of attack, distance, and rotation by arrows/escape (esc changes between AOA and Distance).

The Problem: It desync me all the time each time I test it on the multiplayer with a friend. It works in single player just fine. Can anyone help me with it, and try to keep it MPI as well.
Collapse JASS:
scope CameraSystem initializer Init
//********************************************************
    globals
        // CAMERA VALUES
        private constant integer ZoomMin        = 300       // Minimum distance from unit
        private constant integer ZoomMax        = 2300      // Maximum distance from unit
//**********************************************************************************************************************************

//**********************************************************************************************************************************
        private boolean array RightArrow
        private boolean array LeftArrow
        private boolean array UpArrow
        private boolean array DownArrow
        private boolean array Escape
        private real array Rotation
        private real array Zoom
        private real array AngleOfAttack
        private unit array ZUnit
        public boolean array CameraB
    endglobals
    
    // InitTrigger Condition - Checks if owning unit is TriggerPlayer and is HERO
    function InitTrigger_Cond takes nothing returns boolean
        return GetOwningPlayer(GetTriggerUnit()) == GetTriggerPlayer() and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO)
    endfunction

    // InitTrigger Actions - set the predefined values before the loop (Setting the default camera)
    function InitTrigger_Actions takes nothing returns nothing
        set ZUnit[GetPlayerId(GetTriggerPlayer())] = GetTriggerUnit() 
        set Zoom[GetPlayerId(GetTriggerPlayer())] = 2000
        set Rotation[GetPlayerId(GetTriggerPlayer())] = GetUnitFacing(ZUnit[GetPlayerId(GetTriggerPlayer())])
        set AngleOfAttack[GetPlayerId(GetTriggerPlayer())] = -10
        set Escape[GetPlayerId(GetTriggerPlayer())] = false
        set CameraB[GetPlayerId(GetTriggerPlayer())] = true
    endfunction
    
    // EscapeTrigger Actions
    function Escape_Actions takes nothing returns nothing
        if (Escape[GetPlayerId(GetTriggerPlayer())] == false) then
            set Escape[GetPlayerId(GetTriggerPlayer())] = true
            call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, "Angle of Attack")
        else
            set Escape[GetPlayerId(GetTriggerPlayer())] = false
            call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, "Zoom")
        endif
    endfunction
    
    // Actions - changes the value to true or false depending on player's action
    function RightPress_Actions takes nothing returns nothing
        set RightArrow[GetPlayerId(GetTriggerPlayer())] = true
    endfunction
    
    function LeftPress_Actions takes nothing returns nothing
        set LeftArrow[GetPlayerId(GetTriggerPlayer())] = true
    endfunction
    
    function UpPress_Actions takes nothing returns nothing
        set UpArrow[GetPlayerId(GetTriggerPlayer())] = true
    endfunction
    
    function DownPress_Actions takes nothing returns nothing
        set DownArrow[GetPlayerId(GetTriggerPlayer())] = true
    endfunction
    
    function RightRelease_Actions takes nothing returns nothing
        set RightArrow[GetPlayerId(GetTriggerPlayer())] = false
    endfunction
    
    function LeftRelease_Actions takes nothing returns nothing
        set LeftArrow[GetPlayerId(GetTriggerPlayer())] = false
    endfunction
    
    function UpRelease_Actions takes nothing returns nothing
        set UpArrow[GetPlayerId(GetTriggerPlayer())] = false
    endfunction
    
    function DownRelease_Actions takes nothing returns nothing
        set DownArrow[GetPlayerId(GetTriggerPlayer())] = false
    endfunction
        
    // Loop Actions - Loops and update the camera based on the previous actions
    function ApplyCam takes integer p returns nothing
        local real height = GetCameraField(CAMERA_FIELD_ZOFFSET) + GetLocationZ(GetUnitLoc(ZUnit[p])) - GetCameraTargetPositionZ()
        if (RightArrow[p] == true) then
            set Rotation[p] = Rotation[p]+10
        endif
        if (LeftArrow[p] == true) then
            set Rotation[p] = Rotation[p]-10
        endif
        if (UpArrow[p] == true) then
            if (Escape[p] == false) then
                set Zoom[p] = Zoom[p]-50
                if (Zoom[p] < ZoomMin) then
                    set Zoom[p] = Zoom[p]+50
                endif
            elseif (Escape[p] == true) then
                set AngleOfAttack[p] = AngleOfAttack[p] - 5
                if (AngleOfAttack[p] < -50) then
                    set AngleOfAttack[p] = AngleOfAttack[p] + 5
                endif
            endif
        endif
        if (DownArrow[p] == true) then
            if (Escape[p] == false) then
                set Zoom[p] = Zoom[p]+50
                if (Zoom[p] > ZoomMax) then
                    set Zoom[p] = Zoom[p]-50
                endif
            elseif (Escape[p] == true) then
                set AngleOfAttack[p] = AngleOfAttack[p] + 5
                if (AngleOfAttack[p] > 0) then
                    set AngleOfAttack[p] = AngleOfAttack[p] - 5
                endif
            endif
        endif
        if CameraB[p] == true then
            call SetCameraTargetController(ZUnit[p], 0, 0, true)
            call SetCameraField(CAMERA_FIELD_ROTATION, Rotation[p], 0.10)
            call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, Zoom[p], 0.10)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, height, 0.10)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, AngleOfAttack[p], 0.10)
        endif
    endfunction
    
    function Loop_Actions takes nothing returns nothing
        local integer p = GetPlayerId(GetLocalPlayer())
        if ZUnit[p] != null then
            call ApplyCam(p)
        endif
    endfunction

    function Init takes nothing returns nothing
        local trigger InitTrigger = CreateTrigger()
        local trigger RightPressTrigger = CreateTrigger()
        local trigger LeftPressTrigger = CreateTrigger()
        local trigger UpPressTrigger = CreateTrigger()
        local trigger DownPressTrigger = CreateTrigger()
        local trigger RightReleaseTrigger = CreateTrigger()
        local trigger LeftReleaseTrigger = CreateTrigger()
        local trigger UpReleaseTrigger = CreateTrigger()
        local trigger DownReleaseTrigger = CreateTrigger()
        local trigger LoopTrigger = CreateTrigger()
        local trigger EscapeTrigger = CreateTrigger()
        local integer i = MinPlayers-1
        loop
            exitwhen i > MaxPlayers-1
                call TriggerRegisterPlayerUnitEvent(InitTrigger, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
                call TriggerRegisterPlayerEvent(RightPressTrigger, Player(i), EVENT_PLAYER_ARROW_RIGHT_DOWN)
                call TriggerRegisterPlayerEvent(LeftPressTrigger, Player(i), EVENT_PLAYER_ARROW_LEFT_DOWN)
                call TriggerRegisterPlayerEvent(UpPressTrigger, Player(i), EVENT_PLAYER_ARROW_UP_DOWN)
                call TriggerRegisterPlayerEvent(DownPressTrigger, Player(i), EVENT_PLAYER_ARROW_DOWN_DOWN)
                call TriggerRegisterPlayerEvent(RightReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_RIGHT_UP)
                call TriggerRegisterPlayerEvent(LeftReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_LEFT_UP)
                call TriggerRegisterPlayerEvent(UpReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_UP_UP)
                call TriggerRegisterPlayerEvent(DownReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_DOWN_UP)
                call TriggerRegisterPlayerEvent(EscapeTrigger, Player(i), EVENT_PLAYER_END_CINEMATIC)
                set i = i + 1
        endloop
        
        // InitTrigger
        call TriggerAddCondition(InitTrigger, Filter(function InitTrigger_Cond))
        call TriggerAddAction(InitTrigger, function InitTrigger_Actions)
        
        // Arrow Actions
        call TriggerAddAction(RightPressTrigger, function RightPress_Actions)
        call TriggerAddAction(LeftPressTrigger, function LeftPress_Actions)
        call TriggerAddAction(UpPressTrigger, function UpPress_Actions)
        call TriggerAddAction(DownPressTrigger, function DownPress_Actions)
        call TriggerAddAction(RightReleaseTrigger, function RightRelease_Actions)
        call TriggerAddAction(LeftReleaseTrigger, function LeftRelease_Actions)
        call TriggerAddAction(UpReleaseTrigger, function UpRelease_Actions)
        call TriggerAddAction(DownReleaseTrigger, function DownRelease_Actions)
        
        // LoopTrigger
        call TriggerRegisterTimerEvent(LoopTrigger, 0.10, true)
        call TriggerAddAction(LoopTrigger, function Loop_Actions)
        
        // EscapeTrigger
        call TriggerAddAction(EscapeTrigger, function Escape_Actions)
    endfunction
endscope

As for CameraB[] - It's in initialization trigger with initial false.
I realize that my coding may seems messy but I have been working on this all day trying to fix this desync problem. It would be appreciated if you were able to provide some assistance.
04-08-2010, 10:43 PM#2
Ammorth
GetUnitLoc() creates a location, which you are creating locally (cause you are calling ApplyCam in a local player block. Instead, use a public constant location and move it to the position of the unit. This way you won't create the location locally.

Collapse JASS:
globals
    private location tempLoc = Location(0, 0)
endglobals

...

    function ApplyCam takes integer p returns nothing
        local real height = GetCameraField(CAMERA_FIELD_ZOFFSET)  - GetCameraTargetPositionZ()
        call MoveLocation(tempLoc, GetUnitX(ZUnit[p]), GetUnitY(ZUnit[p]))
        set height = height + GetLocationZ(tempLoc)
        if (RightArrow[p] == true) then
...

Btw: Since you are keeping all the data for each camera local, you don't even have to use arrays for all of your variables.

Edit: Like this:

Collapse JASS:
scope CameraSystem initializer Init
//********************************************************
    globals
        // CAMERA VALUES
        private constant integer ZoomMin        = 300       // Minimum distance from unit
        private constant integer ZoomMax        = 2300      // Maximum distance from unit
//**********************************************************************************************************************************

//**********************************************************************************************************************************
        // since we don't use arrays, we need to assign starting values so they are not uninitializer (causes a thread to terminate when reading uninitialized variables).
        // All these value are local (except ZUnit), so the values will be different for each player.  Therefore, don't modify globals values/states based on these values.
        private boolean RightArrow = false
        private boolean LeftArrow = false
        private boolean UpArrow = false
        private boolean DownArrow = false
        private boolean Escape = false
        private real Rotation = 0
        private real Zoom = 0
        private real AngleOfAttack = 0
        private unit array ZUnit // when dealing with handles we should work globally, since handles could be de-indexed at different times, causing desyncs.
        public boolean CameraB = false
        
        // we declare the strings globally so we can use them locally without desyncing the string table.
        private constant string TextAoA = "Angle of Attack"
        private constant string TextZoom = "Zoom"
        
        // again, a global location so we don't change handles locally
        private constant location tempLoc = Location(0, 0)
    endglobals
    
    // InitTrigger Condition - Checks if owning unit is TriggerPlayer and is HERO
    function InitTrigger_Cond takes nothing returns boolean
        return GetOwningPlayer(GetTriggerUnit()) == GetTriggerPlayer() and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO)
    endfunction

    // InitTrigger Actions - set the predefined values before the loop (Setting the default camera)
    function InitTrigger_Actions takes nothing returns nothing
        set ZUnit[GetPlayerId(GetTriggerPlayer())] = GetTriggerUnit()
        if GetLocalPlayer() == GetTriggerPlayer() then // local block
            set Zoom = 2000
            set Rotation = GetUnitFacing(ZUnit[GetPlayerId(GetTriggerPlayer())])
            set AngleOfAttack = -10
            set Escape = false
            set CameraB = true
        endif
    endfunction
    
    // EscapeTrigger Actions
    function Escape_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            if (Escape == false) then
                set Escape = true
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, TextAoA)
            else
                set Escape = false
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, TextZoom)
            endif
        endif
    endfunction
    
    // Actions - changes the value to true or false depending on player's action
    function RightPress_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set RightArrow = true
        endif
    endfunction
    
    function LeftPress_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set LeftArrow = true
        endif
    endfunction
    
    function UpPress_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set UpArrow = true
        endif
    endfunction
    
    function DownPress_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set DownArrow = true
        endif
    endfunction
    
    function RightRelease_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set RightArrow = false
        endif
    endfunction
    
    function LeftRelease_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set LeftArrow = false
        endif
    endfunction
    
    function UpRelease_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set UpArrow = false
        endif
    endfunction
    
    function DownRelease_Actions takes nothing returns nothing
        if GetLocalPlayer() == GetTriggerPlayer() then
            set DownArrow = false
        endif
    endfunction
        
    // Loop Actions - Loops and update the camera based on the previous actions
    function ApplyCam takes integer p returns nothing
        local real height = GetCameraField(CAMERA_FIELD_ZOFFSET)  - GetCameraTargetPositionZ()
        call MoveLocation(tempLoc, GetUnitX(ZUnit[p]), GetUnitY(ZUnit[p]))
        set height = height + GetLocationZ(tempLoc)

        if (RightArrow == true) then
            set Rotation = Rotation+10
        endif
        if (LeftArrow == true) then
            set Rotation = Rotation-10
        endif
        if (UpArrow == true) then
            if (Escape == false) then
                set Zoom = Zoom-50
                if (Zoom < ZoomMin) then
                    set Zoom = Zoom+50
                endif
            elseif (Escape == true) then
                set AngleOfAttack = AngleOfAttack - 5
                if (AngleOfAttack < -50) then
                    set AngleOfAttack = AngleOfAttack + 5
                endif
            endif
        endif
        if (DownArrow == true) then
            if (Escape == false) then
                set Zoom = Zoom+50
                if (Zoom > ZoomMax) then
                    set Zoom = Zoom-50
                endif
            elseif (Escape == true) then
                set AngleOfAttack = AngleOfAttack + 5
                if (AngleOfAttack > 0) then
                    set AngleOfAttack = AngleOfAttack - 5
                endif
            endif
        endif
        if CameraB == true then
            call SetCameraTargetController(ZUnit[p], 0, 0, true)
            call SetCameraField(CAMERA_FIELD_ROTATION, Rotation, 0.10)
            call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, Zoom, 0.10)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, height, 0.10)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, AngleOfAttack, 0.10)
        endif
    endfunction
    
    function Loop_Actions takes nothing returns nothing
        local integer p = GetPlayerId(GetLocalPlayer())
        if ZUnit[p] != null then
            call ApplyCam(p)
        endif
    endfunction

    function Init takes nothing returns nothing
        local trigger InitTrigger = CreateTrigger()
        local trigger RightPressTrigger = CreateTrigger()
        local trigger LeftPressTrigger = CreateTrigger()
        local trigger UpPressTrigger = CreateTrigger()
        local trigger DownPressTrigger = CreateTrigger()
        local trigger RightReleaseTrigger = CreateTrigger()
        local trigger LeftReleaseTrigger = CreateTrigger()
        local trigger UpReleaseTrigger = CreateTrigger()
        local trigger DownReleaseTrigger = CreateTrigger()
        local trigger LoopTrigger = CreateTrigger()
        local trigger EscapeTrigger = CreateTrigger()
        local integer i = MinPlayers-1
        call BJDebugMsg("bah2")
        loop
            exitwhen i > MaxPlayers-1
                call TriggerRegisterPlayerUnitEvent(InitTrigger, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
                call TriggerRegisterPlayerEvent(RightPressTrigger, Player(i), EVENT_PLAYER_ARROW_RIGHT_DOWN)
                call TriggerRegisterPlayerEvent(LeftPressTrigger, Player(i), EVENT_PLAYER_ARROW_LEFT_DOWN)
                call TriggerRegisterPlayerEvent(UpPressTrigger, Player(i), EVENT_PLAYER_ARROW_UP_DOWN)
                call TriggerRegisterPlayerEvent(DownPressTrigger, Player(i), EVENT_PLAYER_ARROW_DOWN_DOWN)
                call TriggerRegisterPlayerEvent(RightReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_RIGHT_UP)
                call TriggerRegisterPlayerEvent(LeftReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_LEFT_UP)
                call TriggerRegisterPlayerEvent(UpReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_UP_UP)
                call TriggerRegisterPlayerEvent(DownReleaseTrigger, Player(i), EVENT_PLAYER_ARROW_DOWN_UP)
                call TriggerRegisterPlayerEvent(EscapeTrigger, Player(i), EVENT_PLAYER_END_CINEMATIC)
                set i = i + 1
        endloop
        
        // InitTrigger
        call TriggerAddCondition(InitTrigger, Filter(function InitTrigger_Cond))
        call TriggerAddAction(InitTrigger, function InitTrigger_Actions)
        
        // Arrow Actions
        call TriggerAddAction(RightPressTrigger, function RightPress_Actions)
        call TriggerAddAction(LeftPressTrigger, function LeftPress_Actions)
        call TriggerAddAction(UpPressTrigger, function UpPress_Actions)
        call TriggerAddAction(DownPressTrigger, function DownPress_Actions)
        call TriggerAddAction(RightReleaseTrigger, function RightRelease_Actions)
        call TriggerAddAction(LeftReleaseTrigger, function LeftRelease_Actions)
        call TriggerAddAction(UpReleaseTrigger, function UpRelease_Actions)
        call TriggerAddAction(DownReleaseTrigger, function DownRelease_Actions)
        
        // LoopTrigger
        call TriggerRegisterTimerEvent(LoopTrigger, 0.10, true)
        call TriggerAddAction(LoopTrigger, function Loop_Actions)
        
        // EscapeTrigger
        call TriggerAddAction(EscapeTrigger, function Escape_Actions)
        call BJDebugMsg("bah3")
    endfunction
endscope

This shouldn't cause any desyncs.