HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Why is this condition causing desyncs?

05-03-2008, 05:28 PM#1
Opossum
This is a 3rd person camera system that is supposed to only work on players that have already chosen a hero. All other players get the initial hero selection camera setup.
Collapse JASS:
function Trig_CameraPeriodic_Actions takes nothing returns nothing
    local integer i = 0
    
    local real unitx
    local real unity
    local real unitz
    
    local real panx
    local real pany
    
    local real offsetx
    local real offsety
    local real offsetz
    
    local real anticlipangle
    local real angleofattack

    loop
        exitwhen i == 12
        if GetLocalPlayer() == Player(i) then
            if udg_Hero[i] == null then // This is the condition that's causing problems. Everything else from here on seems to work perfectly without this condition.
                call CameraSetupApply(gg_cam_Character_Selection, true, false)
            else                
                set angleofattack = bj_RADTODEG * GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)
                set unitx = GetUnitX(udg_Hero[i])
                set unity = GetUnitY(udg_Hero[i])
                set offsetx = GetCameraEyePositionX() + 500 * Cos(GetCameraField(CAMERA_FIELD_ROTATION) + bj_PI)
                set offsety = GetCameraEyePositionY() + 500 * Sin(GetCameraField(CAMERA_FIELD_ROTATION) + bj_PI)
                if angleofattack > 345 then
                    call PanCameraToTimed(unitx, unity, 0.5)
                else
                    set panx = unitx + (1380 - 4*angleofattack) * Cos(bj_DEGTORAD*GetUnitFacing(udg_Hero[i]))
                    set pany = unity + (1380 - 4*angleofattack) * Sin(bj_DEGTORAD*GetUnitFacing(udg_Hero[i]))
                    call PanCameraToTimed(panx, pany, 0.5)
                endif
                set unitz = GetLocationZ(Location(unitx, unity))
                set offsetz = GetLocationZ(Location(offsetx, offsety)) - unitz
                call RemoveLocation(Location(unitx, unity))
                call RemoveLocation(Location(offsetx, offsety))
                set anticlipangle = 365 - bj_RADTODEG * Atan((offsetz-GetCameraField(CAMERA_FIELD_ZOFFSET)) / GetCameraField(CAMERA_FIELD_TARGET_DISTANCE))
                if udg_ControlableAoA[i] > anticlipangle then
                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, anticlipangle, 0.5)
                else
                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, udg_ControlableAoA[i], 0.5)
                endif
                call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 2900-7.5*angleofattack, 0.5)
                call SetCameraField(CAMERA_FIELD_ZOFFSET, GetCameraField(CAMERA_FIELD_ZOFFSET) - GetCameraTargetPositionZ() + unitz + GetUnitFlyHeight(udg_Hero[i]) + 100, 0.5)
                call SetCameraField(CAMERA_FIELD_ROTATION, GetUnitFacing(udg_Hero[i]) + udg_ControlableRot[i], 0.5)
            endif
        endif
        set i = i+1
    endloop
    
endfunction

//===========================================================================
function InitTrig_CameraPeriodic takes nothing returns nothing
    set gg_trg_CameraPeriodic = CreateTrigger(  )
    call TriggerAddAction( gg_trg_CameraPeriodic, function Trig_CameraPeriodic_Actions )
    call TriggerRegisterTimerEventPeriodic(gg_trg_CameraPeriodic, 0.1)
endfunction

The strange thing is that the whole 3rd person part (from the first "else" on up to "endif") seems to work on multiplayer as long as there isn't this condition "if udg_Hero[i] == null" implemented. With that condition in the function the other player is DCed immediately after either one chose a character (meaning udg_Hero gets a value that is != null).
I also already tried to use that condition before the GetLocalPlayer() condition but that won't work either.

So what can I do to make this condition not disc other players and why is just CHECKING a global variable causing desyncs?
05-03-2008, 06:15 PM#2
Captain Griffen
Creating locations with GetLocalPlayer is a no-no - don't create handles locally. If the condition isn't there, then all players will have handles created equally. If the condition is there, some may have different numbers created, leading to a desync.
05-03-2008, 07:09 PM#3
Opossum
Hmm... I guess I've gotta rewrite parts of that trigger into global code then...

Thanks for your help :)

stupid handles...
05-03-2008, 07:29 PM#4
Here-b-Trollz
You can use GetCameraTargetPositionZ() and GetCameraEyePositionZ() instead of creating a location at the target point.
05-03-2008, 07:54 PM#5
Opossum
Quote:
Originally Posted by Here-b-Trollz
You can use GetCameraTargetPositionZ() and GetCameraEyePositionZ() instead of creating a location at the target point.

That wouldn't help me in this case. The offsetz is the height of a certain location that is 500 units behind the camera eye. This terrain height value is used to calculate a camera angle that prevents the camera from falling below the terrain (or that you click on a cliff that is behind you but you can't even see). GetCameraEyePositionZ would just give me the height of the camera eye.

GetCameraTargetPositionZ for unitz would work though.


I just can't seem to get it to work... The locations depend on local calculations which makes it impossible for me to get the offset height.
On the other hand making the whole code global is impossible because I don't see a way to let functions like GetCameraField() return a global value (like a function "GetPlayerCameraField()").

BWARGH seems like I'll have to rework/delete that whole anti-clipping stuff...


Edit: Oh wow it's working now oO. I globalize everything that was globalizable (this word is mine. Don't steal it!). So now it's an ugly hybrid of local and global code and it works perfectly. This is how it looks now:
Collapse JASS:
function Trig_CameraPeriodic_Actions takes nothing returns nothing
    local integer i = 0
    
    local real unitx
    local real unity
    local real unitz
    
    local real panx
    local real pany
    
    local real offsetx
    local real offsety
    local real offsetz
    
    local real anticlipangle
    local real angleofattack
    local real rotation

    loop
        exitwhen i == MAXPLAYERS
        if udg_Hero[i] == null then
            call CameraSetupApplyForPlayer(true, gg_cam_Character_Selection, Player(i), 0.1)
        else
            set angleofattack = bj_RADTODEG * GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)
                set unitx = GetUnitX(udg_Hero[i])
                set unity = GetUnitY(udg_Hero[i])
            set rotation = GetCameraField(CAMERA_FIELD_ROTATION) + bj_PI
            set offsetx = GetCameraEyePositionX() + 500 * Cos(rotation)
            set offsety = GetCameraEyePositionY() + 500 * Sin(rotation)
            if angleofattack > 345 then
                call PanCameraToTimedForPlayer(Player(i), unitx, unity, 0.5)
            else
                set panx = unitx + (1380 - 4*angleofattack) * Cos(bj_DEGTORAD*GetUnitFacing(udg_Hero[i]))
                set pany = unity + (1380 - 4*angleofattack) * Sin(bj_DEGTORAD*GetUnitFacing(udg_Hero[i]))
                call PanCameraToTimedForPlayer(Player(i), panx, pany, 0.5)
            endif
            set unitz = GetLocationZ(Location(unitx, unity))
            set offsetz = GetLocationZ(Location(offsetx, offsety)) - unitz
            call RemoveLocation(Location(unitx, unity))
            call RemoveLocation(Location(offsetx, offsety))
            set anticlipangle = 365 - bj_RADTODEG * Atan((offsetz-GetCameraField(CAMERA_FIELD_ZOFFSET)) / GetCameraField(CAMERA_FIELD_TARGET_DISTANCE))
            if udg_ControlableAoA[i] > anticlipangle then
                call SetCameraFieldForPlayer(Player(i), CAMERA_FIELD_ANGLE_OF_ATTACK, anticlipangle, 0.5)
            else
                call SetCameraFieldForPlayer(Player(i), CAMERA_FIELD_ANGLE_OF_ATTACK, udg_ControlableAoA[i], 0.5)
            endif
            call SetCameraFieldForPlayer(Player(i), CAMERA_FIELD_TARGET_DISTANCE, 2900-7.5*angleofattack, 0.5)
            call SetCameraFieldForPlayer(Player(i), CAMERA_FIELD_ZOFFSET, GetCameraField(CAMERA_FIELD_ZOFFSET) - GetCameraTargetPositionZ() + unitz + GetUnitFlyHeight(udg_Hero[i]) + 100, 0.5)
            call SetCameraFieldForPlayer(Player(i), CAMERA_FIELD_ROTATION, GetUnitFacing(udg_Hero[i]) + udg_ControlableRot[i], 0.5)
        endif
        set i = i+1
    endloop
    
endfunction
I'll never figure out that whole local/globals stuff...
05-03-2008, 09:26 PM#6
Captain Griffen
...okay, seriously, I've just noticed what you're doing with locations and...

Okay, go look up programming objects on Wikipedia, and read up some more about leaks. And I mean it about looking up objects - read up on pointers as well.

A better option would have been to create a single location outside the local player section, and then just move it where it needed to be, and then remove it outside the local player section.