| 08-06-2006, 10:53 PM | #1 |
Hi again! I want to use the following, and I'm not sure whether this creates a desync or not: Trigger: ![]() Custom script: if GetLocalPlayer()==GetTriggerPlayer() then
![]() Custom script: set Loc2=GetCameraTargetPositionLoc()
![]() Custom script: endifThis trigger gives Loc2 the position of the cam of the the triggering player. Now when I creat any unit at Loc2... Is the unit created for all players at the same position? namely at Loc2 OR is the unit created at the center of the map for the others players? OR even the unit isn't created for the others? The problem I have is, that I want to creat a unit if any player presses "escape" at the triggering players cameraposition, so that when the same player presses esc a 2nd time he will be paned to the created unit and the unit will be deleted. EDIT1: Or instead of creating a unit... what is this good for: native CreateCameraSetup Should I store the location information in a var array for every player so that there won't be a desync conflict?, if there would be a desync... EDIT2: Help please... |
| 08-07-2006, 01:47 AM | #2 |
You'll have to sync the camera target x/y values. Information on that can be found here: http://www.wc3jass.com/viewtopic.php?t=2676 |
| 08-07-2006, 10:15 AM | #3 | |
Thanks for joining PitzerMike, but I have read this linked thread already before I created this thread... I reread the thread a 2nd time and now I use this SyncInteger function: JASS:// optimized SyncInteger function for 12 bits function Sync12BitInteger takes player p, integer unsynced returns integer local integer array source_int local integer array target_int local unit array u local integer i = 0 local group sel = CreateGroup() local unit c = null local integer synced = 0 loop // extract the bits exitwhen i >= 12 set source_int[i] = ModuloInteger(unsynced, 2) set unsynced = unsynced / 2 set i = i + 1 endloop set i = 0 loop // create units to select exitwhen i >= 12 set u[i] = CreateUnit(p, 'nshf', GetStartLocationX(GetPlayerStartLocation(p)), GetStartLocationY(GetPlayerStartLocation(p)), 0) set i = i + 1 endloop call SyncSelections() // save old selection call GroupEnumUnitsSelected(sel, p, null) if (GetLocalPlayer() == p) then call ClearSelection() set i = 0 loop // send bits exitwhen i >= 12 if source_int[i] == 0 then call SelectUnit(u[i], false) else call SelectUnit(u[i], true) endif set i = i + 1 endloop endif //call TriggerSleepAction(0) call SyncSelections() set i = 0 loop // read bits exitwhen i >= 12 if IsUnitSelected(u[i], p) then set target_int[i] = 1 else set target_int[i] = 0 endif set i = i + 1 endloop if (GetLocalPlayer() == p) then call ClearSelection() endif loop // restore old selection set c = FirstOfGroup(sel) exitwhen c == null if (GetLocalPlayer() == p) then call SelectUnit(c, true) endif call GroupRemoveUnit(sel, c) endloop call SyncSelections() set i = 0 loop // remove units to select exitwhen i >= 12 call RemoveUnit(u[i]) set i = i + 1 endloop set i = 11 loop // rebuild integer exitwhen i < 0 set synced = 2 * synced + target_int[i] set i = i - 1 endloop return synced endfunction function GetGridId takes real x, real y returns integer local real dx = (GetRectMaxX(GetWorldBounds()) - GetRectMinX(GetWorldBounds())) / 64 local real dy = (GetRectMaxY(GetWorldBounds()) - GetRectMinY(GetWorldBounds())) / 64 local integer xi = R2I((x - GetRectMinX(GetWorldBounds())) / dx) local integer yi = R2I((y - GetRectMinY(GetWorldBounds())) / dy) return (yi * 64) + xi endfunction function GetGridIdX takes integer id returns real local real dx = (GetRectMaxX(GetWorldBounds()) - GetRectMinX(GetWorldBounds())) / 64 return (ModuloInteger(id, 64) + 0.5) * dx + GetRectMinX(GetWorldBounds()) endfunction function GetGridIdY takes integer id returns real local real dy = (GetRectMaxY(GetWorldBounds()) - GetRectMinY(GetWorldBounds())) / 64 local integer temp = id / 64 return (temp + 0.5) * dy + GetRectMinY(GetWorldBounds()) endfunction function SyncLoc takes player p, location l returns location local integer s = Sync12BitInteger(p,GetGridId(GetLocationX(l),GetLocationY(l))) local location synced = Location(GetGridIdX(s),GetGridIdY(s)) call RemoveLocation(l) return synced endfunction I tested it with 2 players over LAN and for player1 it works almost right 1) When I use these functions I get 7 flying sheeps for short! (selected and also created at the map, which looks horrible) -> my map can have till 8 human players, so do I get 7 because of that? Actualy I should get arround 12 units as the trigger says... -> but why do I get sheeps at all??? I want no sheeps *argh* 2) When I try to create a unit for player6 over the location: JASS:local location synced= SyncLoc(GetTriggerPlayer(),GetCameraTargetPositionLoc()) A quote from you PitzerMike: Quote:
What can I delete from the trigger and what do I have to change and how to have no sheeps and selection? Ah, and btw: Everytime I read a post of yours Mike I'm getting very hungry! |
| 08-07-2006, 03:48 PM | #4 |
Of course you will not want to create sheep but an invisible dummy unit instead. So you can replace the 'nshf' in this code line: JASS:set u[i] = CreateUnit(p, 'nshf', GetStartLocationX(GetPlayerStartLocation(p)), GetStartLocationY(GetPlayerStartLocation(p)), 0) with the unit type id of the invisible dummy unit. Alternatively, as already mentioned you could use preplaced units, then you wouldn't have to create new units whenever you sync a value. To do that you could simply place 12 of your dummy units for each player, save them to an array and then replace the above-shown code line with something like: JASS:u[i] = udg_yourunitarray[GetPlayerId(p) * 12 + i] and remove the loop that kills the selector units at the end of the script JASS:set i = 0 loop // remove units to select exitwhen i >= 12 call RemoveUnit(u[i]) set i = i + 1 endloop That way the selector units don't have to be re-created every time. It can't work for player 6 if only 2 players are in the game. Player 6 won't actually have a camera position if he's not in the game. EDIT: And please save GetWorldBounds() to a variable at initialization and use that instead of calling GetWorldBounds() over and over, it leaks. |
| 08-07-2006, 04:06 PM | #5 | |
1) Quote:
So, what I have is: Player Red (1) is in the game Player Orange (6) is in the game (These are the 2 players) When I use these triggers with (1) then everything is ok When I use these triggers with (6) then, as said, there is no camera detected For TriggerPlayer: Trigger: Custom script: local location synced= SyncLoc(GetTriggerPlayer(),GetCameraTargetPositionLoc())GetTriggerPlayer would be Player(5) for Orange... I don't understand the problem. Every player constantly has any camera position! Or what do I think wrong here... Anyhow we must have misunderstood us... -> If I start a game with only 1 player and for that player I choose Player(5) - Orange, then it works again! So what causes this problem with 2 players? I FOUND OUT THAT IT ONLY WORKS FOR THE ONE WHO OPENED THE MAP! I NOW KNOW FROM WHAT FUNC THE PROBLEM COMES, AND IT IS NO TRIGGER OF MINE!!! I used this original trigger from AIAndy & PipeDream and the same problem occured (cameraposition of joiners is always at map bottom in the left corner): JASS:function SyncLoc takes player p, location l returns location local integer s = Sync12BitInteger(p,GetGridId(GetLocationX(l),GetLocationY(l))) local location synced = Location(GetGridIdX(s),GetGridIdY(s)) call RemoveLocation(l) return synced endfunction function PingCamera takes player p returns nothing local location synced= SyncLoc(p,GetCameraTargetPositionLoc()) call PingMinimap(GetLocationX(synced),GetLocationY(synced),5.0) endfunction This is the point where I seriously need help! I have no idea what is wrong in these complicated triggers... PitzerMike? If you don't believe, then try a map with these triggers with 2 players and let the one who joined fire this trigger. 2) So the units must be selected? I only ask because you see the selected units very shortly flushing in the menu everytime they get selected. Hmmm... then what would happen if I give them the ability locust / 'Aloc'? |
| 08-08-2006, 09:59 AM | #6 | |
Quote:
If you gave them locust the whole thing wouldn't work. Because the system is based on syncing selections. However, you can simply give them an unselectable dummy model, disable their selection circle (negative height), shadow and minimap display and you'll not notice the selector units any more. I'm not sure what's wrong for the other players. I'll try to find my original test map in which it worked. EDIT: Here's the map. It shows that the sync-functions do work. |
| 08-13-2006, 01:14 PM | #7 |
Big thanks for the test map, but I think it also does not work there... How it should work I think: 1st player presses ESC: PC of Player(0) Local index: 2014 Synced index of Player 1: 2014 PC of Player(1) Local index: 752 Synced index of player 1: 2014 2nd player presses ESC: PC of Player(1) Local index: 752 Synced index of player 2: 752 PC of Player(0) Local index: 2014 Synced index of Player 2: 752 BUT, now, how it actually works: 1st player presses ESC: PC of Player(0) Local index: 2014 Synced index of Player 1: 2014 PC of Player(1) Local index: 752 Synced index of player 1: 2014 2nd player presses ESC: PC of Player(1) Local index: 752 Synced index of player 2: 0 PC of Player(0) Local index: 2014 Synced index of Player 2: 0 So, this Result of 0 is wrong or? Shouldn't there be the 752? I used your posted map... |
| 08-13-2006, 01:17 PM | #8 |
try this? JASS:set Loc2=GetCameraTargetPositionLoc() if GetLocalPlayer()==GetTriggerPlayer() then //do stuff with Loc2 variable , but don't do anything that could change the actual gameplay or the count of handles. endif GetCameraTargetPositionLoc acts the same as GetLocalPlayer() |
| 08-13-2006, 01:30 PM | #9 |
All I want is a little system, that works like this: When any player presses ESC, then either save the current camera-position of the trigger player or toggle to his saved camera-position if it already exist... Now, how can I save this camera-position without changing the actual gameplay so that I can check later if it already exist? |
| 08-13-2006, 03:02 PM | #10 |
Well if the saved camera position is not a new location (using MoveLocation) or is a pair of coordinates, and you do not use the saved position for things that affect gameplay, then this should work correctly without desyncs although this is a rather unpredictable area. |
| 08-17-2006, 03:23 PM | #11 |
K, inspired from Vex's idea of making an array var that is only used for the respectively player I wrote this trigger: ("udg_BoolAr" is a boolean array from the Var-menue; "udg_LocAr" is a location array from the Var-menue) JASS:function Trig_Esc_Actions takes nothing returns nothing local texttag tt=CreateTextTag() local group g=CreateGroup() local location Loc1=GetStartLocationLoc(GetPlayerStartLocation(GetTriggerPlayer())) local location Loc2=udg_LocAr[GetPlayerId(GetTriggerPlayer())] if udg_BoolAr[GetPlayerId(GetTriggerPlayer())]==false then // Pan Cam to StartLoc set udg_BoolAr[GetPlayerId(GetTriggerPlayer())]=true call DisplayTextToForce( GetPlayersAll(), "startloc" ) if GetLocalPlayer()==GetTriggerPlayer() then set udg_LocAr[GetPlayerId(GetTriggerPlayer())]=GetCameraTargetPositionLoc() call SetCameraPosition(GetLocationX(Loc1),GetLocationY(Loc1)) endif set g=GetUnitsInRangeOfLocMatching(64,Loc1,null) set bj_groupCountUnits=0 call ForGroup(g, function CountUnitsInGroupEnum) if bj_groupCountUnits==1 then call SelectUnitForPlayerSingle(FirstOfGroup(g),GetTriggerPlayer()) endif call SetTextTagText(tt,StringCase(GetPlayerName(GetTriggerPlayer()), true) + ",|n|cffC000FF>Escape<|r |cffFF80FFdrücken für letzten Punkt.|r",0.018) call SetTextTagPos(tt,GetLocationX(Loc1),GetLocationY(Loc1),10) else // Pan Cam to LastLoc set udg_BoolAr[GetPlayerId(GetTriggerPlayer())]=false call DisplayTextToForce( GetPlayersAll(), "lastloc" ) if GetLocalPlayer()==GetTriggerPlayer() then set udg_LocAr[GetPlayerId(GetTriggerPlayer())]=Loc1 call SetCameraPosition(GetLocationX(Loc2),GetLocationY(Loc2)) endif call SetTextTagText(tt,"|cffC000FF>Escape<|r |cffFF80FFdrücken|num Perspektive zu ändern.|r",0.018) call SetTextTagPos(tt,GetLocationX(Loc2),GetLocationY(Loc2),10) endif call SetTextTagPermanent(tt,false) call SetTextTagLifespan(tt,5) call SetTextTagVisibility(tt,(GetLocalPlayer()==GetTriggerPlayer())) // ClearMemory call DestroyGroup(g) call RemoveLocation(Loc1) call RemoveLocation(Loc2) set g=null set Loc1=null set Loc2=null set tt=null endfunction //=========================================================================== function InitTrig_Esc takes nothing returns nothing set gg_trg_Esc = CreateTrigger( ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(0) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(1) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(2) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(3) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(5) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(6) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(7) ) call TriggerRegisterPlayerEventEndCinematic( gg_trg_Esc, Player(10) ) call TriggerAddAction( gg_trg_Esc, function Trig_Esc_Actions ) endfunction For 1 player it already works quite fine, but I still have to test, if it really doesn't cause desyncs in games with more players... Perhaps you can give me a few tips whether I should change or correct anything. I would be very glad if some of you have a short look at the trigger. Thanks! EDIT: Please have a look at it... |
| 08-18-2006, 07:51 AM | #12 |
I donot get what the fuss is all about. Plx explain again for me. As far as I understood, you want to create a system that, makes some selection units only selectable for some specific players? Plx reply. EDIT: What do you think of hiding the unit for all players except the special player: JASS:call ShowUnit(selector,GetLocalPlayer()==specificplayer) |
| 08-18-2006, 08:05 AM | #13 | ||
Quote:
Hmmm, ok, I try to explain with an example: 1) Player(0)-RED presses ESC for the very 1st time 2) The current CameraView of RED is saved under location A and the camera of RED instantly pans to location B (any preplaced location) 3) Player(0)-RED presses ESC for a 2nd time 4) The camera of RED instantly pans to location A which was saved in "2)" 5) Player(0)-RED presses ESC for a 3rd time 6) The current CameraView of RED is saved under location A and the camera of RED instantly pans to location B (the preplaced location) . . . I especially want to use this for players who plays my map for the first time. So, it is said at map start, that when they press ESC, then they will get to their main base. When they press ESC again, they will get back to their last location. Quote:
JASS:set g=GetUnitsInRangeOfLocMatching(64,Loc1,null) set bj_groupCountUnits=0 call ForGroup(g, function CountUnitsInGroupEnum) if bj_groupCountUnits==1 then call SelectUnitForPlayerSingle(FirstOfGroup(g),GetTriggerPlayer()) endif |
| 08-18-2006, 08:21 AM | #14 |
Test it out! JASS:globals gamecache udg_somecache //must be initialisized endglobals function home_x takes integer playerid returns real return 0. // the depending players hoe location x endfunction function home_y takes integer playerid returns real return 0. // the depending players hoe location y endfunction function camera_xy takes nothing returns nothing local player p=GetTriggerPlayer() local integer i=GetPlayerId(p) local string s=I2S(i)+"[playerpos]" // if no stored value, boolean will return false //this is at the first time important if not GetStoredBoolean(udg_somecache,s,"[b]") then if GetLocalPlayer()==p then call SetCameraPosition(home_x(i),home_y(i)) // if it does not work, move this part out of the if-then-else call StoreReal(udg_somecache,s,"[x]",GetCameraTargetPositionX()) call StoreReal(udg_somecache,s,"[y]",GetCameraTargetPositionY()) endif call StoreBoolean(udg_somecache,s,"[b]",true) else call FlushStoredBoolean(udg_somecache,s,"[b]") //will make the func return false, as it is flushed/cleaned if GetLocalPlayer()==p then call SetCameraPosition(GetStoredReal(udg_somecache,s,"[x]"),GetStoredReal(udg_somecache,s,"[y]")) endif endif set p=null endfunction function// .... Initalisation of the trigger ..blabla //GC initialisation if udg_somecache==null then call FlushGameCache(InitGameCache("somecache")) set udg_somecache=InitGameCache("somecache") endif If it is true what vex said, this should work EDIT: Code updated |
| 08-18-2006, 01:17 PM | #15 |
Hmmm, I think I get it, but: 1) with more then 1 player it would not work or? I mean the integer var "udg_check"... Mustn't it be an integer array for every player? 2) how does the gamecache work?... I get the Storing and GetStore, but doesn't there leak anything? Don't you have to clean the... oh w8, these are real-values you save to gamecache... so, these are cleared from memory at the end of the trigger automatically? No, that's wrong too, because then you wouldn't store them *argh* So, these real - values stay in memory... and yes, they also have to stay there, otherwise it would not work, but what happens when new real values get stored for the same string s for "x" and "y"? Will the old values just get overwritten or will the old values be lost in memory and there come 2 new values in addition? Sorry, but with gamecache I have almost no experience... |
