| 05-03-2008, 05:28 PM | #1 |
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. 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 |
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 |
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 |
You can use GetCameraTargetPositionZ() and GetCameraEyePositionZ() instead of creating a location at the target point. |
| 05-03-2008, 07:54 PM | #5 | |
Quote:
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: 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 |
| 05-03-2008, 09:26 PM | #6 |
...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. |
