HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Desync Problem with Set Camera Field take a look

04-16-2007, 10:16 AM#1
hobo
Hi guys I have been searching for a few days, on the forums, for a way to make this simple function not desync but as of yet I have failed. I noticed AiAndy wrote a syncinteger function but it did not seem to apply. Or was complicated enough that the variety of uses it could be put to were beyond my initial understanding.

This trigger starts disabled and if someone is moved into the player group ZoomIn this trigger is enabled and their camera's distance to target is changed. My understanding of the problem is that the GetCameraField() returns different numbers for every player as it is a local function operating on each players own camera.

Collapse JASS:
function Trig_ZoomIn_Copy_Actions takes nothing returns nothing
    call ForForce( udg_ZoomIn, SetCameraFieldForPlayer( GetEnumPlayer(), CAMERA_FIELD_TARGET_DISTANCE, ( GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100.00 ), 0.15 ) )
endfunction

//===========================================================================
function InitTrig_ZoomIn_Copy takes nothing returns nothing
    set gg_trg_ZoomIn_Copy = CreateTrigger(  )
    call DisableTrigger( gg_trg_ZoomIn_Copy )
    call TriggerRegisterTimerEventPeriodic( gg_trg_ZoomIn_Copy, 0.15 )
    call TriggerAddAction( gg_trg_ZoomIn_Copy, function Trig_ZoomIn_Copy_Actions )
endfunction


I have tried adding an if/then/else of (if picked player = local player then SetCameraField else do nothing) but that desynced as well. Of course I wrote it more out of hope than logic. I like to code in H.

Anyway I would certainly appreciate any assistance you might be able to render.
04-16-2007, 11:53 AM#2
Toadcop
SetCameraFieldForPlayer and GetCameraFieldForPlayer must be done only for local players !

if GetLocalPlayer()==Player( needed player ) then
call SetCameraFieldForPlayer(...)
endif

and to GetCameraField() must be also be done only for LocalPlayer() but how... you must use something like this !!!

Code:
function GetCamField takes player p,camerafield cf returns real
  if GetLocalPlayer()==p then
    return GetCameraField(cf)
  endif
    return 0.
endfunction

well something like this !

and the rest is so
Code:
function Trig_ZoomIn_Copy_Actions takes nothing returns nothing
    call ForForce( udg_ZoomIn,SetCameraFieldForPlayer( GetEnumPlayer(), CAMERA_FIELD_TARGET_DISTANCE, ( [b]GetCamField[/b](GetEnumPlayer(),CAMERA_FIELD_TARGET_DISTANCE) - 100.00 ), 0.15 )
endfunction

well i would it make a bit different + call ForForce( udg_ZoomIn,"UseCode") so what you have writen here is a syntax error... but it's not the problem

so it must be with out DeSyncs but i have some doubts... you would better use this function

Code:
function SetCamField takes player p,camerafield cf,real val,real dur returns nothing
  if GetLocalPlayer()==p then
    call SetCameraField(cf,GetCameraField(cf)-val (in your case 100),dur)
  endif
endfunction

instead of SetCameraFieldForPlayer() but it's also not the best solution...
04-18-2007, 12:21 AM#3
hobo
Toadcop thank you for the reply! however I don't seem to understand why that would not cause a desync. Wouldn't that cause a trigger to run on one computer and not the others thus causing a desync?
04-18-2007, 04:13 AM#4
Ammorth
Its that GetCameraField() returns different values for different cameras, and seeing how each player has a different camera view, it does just that. What Toadcop said is that you have to do your camera changes locally (for only 1 player) to avoid desyncs.

You could also just set the camera distance to a value, instead of subtracting 100 from their current setting. This would avoid the required JASS and avoid the desyncs (unless you are comfortable with JASS).
04-19-2007, 08:07 PM#5
hobo
Yeah, thats what I was thinking but this seems to cause desyncs
(in Gui for readablilty)


Trigger:
ZoomIn
Collapse Events
Time - Every 0.15 seconds of game time
Conditions
Collapse Actions
Collapse Player Group - Pick every player in ZoomIn and do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(Picked player) Equal to (==) (Local player)
Collapse Then - Actions
Camera - Set (Picked player)'s camera Distance to target to ((Distance to target of the current camera view) - 100.00) over 0.15 seconds
Collapse Else - Actions
Do nothing

And My brain says it shouldn't

Btw the (current distance to target - 100) is for zooming in. I don't think a static height would help for that.
04-19-2007, 11:14 PM#6
Vexorian
functions cause net traffic. GUI's set camera field is a function, not a native. GUI's if then else use functions, and it ends up becoming a mess.

"GUI for readability" is an oxymoron
04-20-2007, 12:50 AM#7
hobo
Obviously this is a bit cleaner but is there a better way than ForForce() so we can omit that second function?


Collapse JASS:
function Trig_ZoomIn_Copy2 takes nothing returns nothing
    if GetEnumPlayer() == GetLocalPlayer()  then
        call SetCameraFieldForPlayer( GetEnumPlayer(), CAMERA_FIELD_TARGET_DISTANCE, ( GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100.00 ), 0.15 )
    endif
endfunction

function Trig_ZoomIn_Copy_Actions takes nothing returns nothing
    call ForForce( udg_ZoomIn, function Trig_ZoomIn_Copy2 )
endfunction

//===========================================================================
function InitTrig_ZoomIn_Copy takes nothing returns nothing
    set gg_trg_ZoomIn_Copy = CreateTrigger(  )
    call DisableTrigger( gg_trg_ZoomIn_Copy )
    call TriggerRegisterTimerEventPeriodic( gg_trg_ZoomIn_Copy, 0.15 )
    call TriggerAddAction( gg_trg_ZoomIn_Copy, function Trig_ZoomIn_Copy_Actions )
endfunction

Sorry if the Gui irks you. My thinking was lots of people can read jass and understand it, fewer read and understand it quickly but everyone can read that silly gui stuff.
Although considering my target audience ( people able and willing to help me) it wasn't the best choice.
04-20-2007, 01:01 AM#8
Vexorian
Just so you know:

Collapse JASS:
function SetCameraFieldForPlayer takes player whichPlayer, camerafield whichField, real value, real duration returns nothing
    if (GetLocalPlayer() == whichPlayer) then
        // Use only local code (no net traffic) within this block to avoid desyncs.
        call SetCameraField(whichField, value, duration)
    endif
endfunction

The problem is with functions inside GetLocalPlayer() blocks. so ForForce is anon-issue in this case, yet ForForce is the most useless function ever and you should not consider it:

Collapse JASS:
function LookIEnumTheForce takes force f returns nothing
 local integer i=0
    loop
         exitwhen i==16
         if (IsPlayerInForce(Player(i),f)) then
               //  ....
         endif
         set i=i+1
    endloop
endfunction
04-20-2007, 01:23 AM#9
wyrmlord
Couldn't you just do:
call SetCameraFieldForPlayer( GetLocalPlayer(), <other arguements> )
04-20-2007, 01:27 AM#10
hobo
Love the function name. Thanks thats a simple and useful replacement.
I would be happy to do this without GetLocalPlayer() if you have any ideas as to how that might be accomplished.

Wyrmlord: if GetEnumPlayer() == GetLocalPlayer() then what's the difference?
But you most definitely don't want every player changing every other players camera based on their own positions, rather than awesome chaos you get boring desync.

What I really need is a way for everyone to agree in what player(x)'s current camera settings and then all agree to change them.
Or at least that's what I think I need... As far as I know this shouldn't work or at least not reliably(and I tested it) as Vexorian pointed out.

Collapse JASS:
function Trig_ZoomIn_Copy2 takes nothing returns nothing
    if GetEnumPlayer() == GetLocalPlayer()  then
        call SetCameraFieldForPlayer( GetEnumPlayer(), CAMERA_FIELD_TARGET_DISTANCE, ( GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100.00 ), 0.15 )
    endif
endfunction
04-20-2007, 01:51 AM#11
Vexorian
Oh come on! you people are really not getting it.


SetCameraFieldForPlayer = function that already uses GetLocalPlayer inside = a function call = would desync if called inside another GetLocalPlayer() block.

Collapse JASS:
    if GetEnumPlayer() == GetLocalPlayer()  then
        call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100.00 , 0.15 )
    endif
04-20-2007, 02:28 AM#12
hobo
Wow... Feeling stupid, thanks for the wake up. ouch...

edit: so this would be the optimal replacement for that crappy Gui trigger I posted earlier?

Collapse JASS:
function Trig_ZoomIn_Actions takes nothing returns nothing
 local integer i=0
    loop
         exitwhen i==16 //should be set to 12 for only human players?
         if (IsPlayerInForce(Player(i),udg_ZoomIn) and (Player(i) == GetLocalPlayer())) then
                call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100.00 , 0.15 )
         endif
         set i=i+1
    endloop
endfunction

//===========================================================================
function InitTrig_ZoomIn takes nothing returns nothing
    set gg_trg_ZoomIn = CreateTrigger(  )
    call DisableTrigger( gg_trg_ZoomIn )
    call TriggerRegisterTimerEventPeriodic( gg_trg_ZoomIn, 0.15 )
    call TriggerAddAction( gg_trg_ZoomIn, function Trig_ZoomIn_Actions )
endfunction
04-20-2007, 04:54 AM#13
Vexorian
that "should" work
04-24-2007, 09:58 PM#14
hobo
Had some problems with that last attempt it worked "some of the time"
so I am testing this now. I moved the getcamerafield call out of the if/then block. we shall see.

Collapse JASS:
function Trig_ZoomIn_Actions takes nothing returns nothing
 local integer i=0
 local real j = (GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) - 100)
    loop
         exitwhen i==12
         if (IsPlayerInForce(Player(i),udg_ZoomIn) and (Player(i) == GetLocalPlayer())) then
                call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, j , 0.15 )
         endif
         set i=i+1
    endloop
endfunction

//===========================================================================
function InitTrig_ZoomIn takes nothing returns nothing
    set gg_trg_ZoomIn = CreateTrigger(  )
    call DisableTrigger( gg_trg_ZoomIn )
    call TriggerRegisterTimerEventPeriodic( gg_trg_ZoomIn, 0.15 )
    call TriggerAddAction( gg_trg_ZoomIn, function Trig_ZoomIn_Actions )
endfunction


EDIT: Hell Yeah it works! Thanks for the help guys. +rep for vex and toad.
To anyone who reads this later, post #11 is the important part. The difference between SetCameraField() and SetCameraFieldForPlayer() is what was causing all my headaches. Feel free to pm me if you have any questions.