Jump to content
Sign in to follow this  
granQ

Join in progress

Recommended Posts

I (and hopefully everyone that reads this thread) has basic knowledge of mission editing, scripting and local/client stuff. We can do the operation flashpoint editing perfectly but the Join in progress is confusing for atleast me.

So people, feel free to post lessons learn, stuff that doesn't work, stuff that works and explinations on what is best.

For instance what I noticed is that if you change markercolor ingame and then a JIP player comes, markers will reset to its orginall color.

Share this post


Link to post
Share on other sites

The main concern about JIP is to remember WHAT IS RUNNING ON WHAT MACHINE in terms of scripts and commands.

For example, say you have a mission where you want to attack a town and as you get within say 500, a bunch of badguys spawn.

Typically this would be done with a trigger that fires when west is present and fires a script (or single use of the bis_fnc_spawngroup function) that makes 20 dudes to shoot at.

The problem is that this trigger will exist for every player that joins the server on their machine AND WILL BE ACTIVATED ONCE FOR EVERY MACHINE eg if 5 players are in the game, 100 dudes would get spawned!

To get around this, and similar problems, you have to understand the concept of LOCALITY - ie is a script being run on the server, on client machines or both.

To continue the example above, to ensure that only 20 dudes are spawned, no matter how many players join, we have to work with the game.

We can't stop the trigger being activated on both server and client machines, but we CAN prevent certain lines of code being executed on client machines. Compare the following lines of code which we could put in the trigger's on activation field:

1. dudes = [(getmarkerpos "town"),east,20] call bis_fnc_spawnGroup;

2. if (isServer) then {dudes = [(getmarkerpos town),east,20] call bis_fnc_spawnGroup;};

The first example would spawn 20 east soldiers PER PLAYER at a marker called town.

The second example would only create the 20 soldiers on the server (but all players would be able to see and shoot them).

Check out Mr. Murrays editing guide, there are some further discussions of MP compatability contained therein.

Or you could do what I did to learn ARMA scripting - depbo the domination! mission and spend 3 weeks figuring out how it all works =]

I'm still not an expert by any means, but I can follow other people's code quite well, I also comment the buggery out of anything I write to enable others to follow it more easily.

Try looking at my operation magpie mission (linked in my sig) for some fairly simple examples of getting JIP to work properly - note I haven't solved ALL my problems, eg, I haven't implemented a way of getting the current state of mission tasks passed to respawned or JIP players yet (ie on JIP, players don't know what tasks have been completed yet).

Read, read and read some more! Then try out some ideas on simple test maps. Then spend 3 days debugging your scripts.

Rinse and repeat for a few weeks and you have your own domination! beater =]

Share this post


Link to post
Share on other sites

question on JIP and tasks_fix i got from "he longest day" mission:

I made a coop helicopter mission that has 10 objectives, but you can only see the first 3 objectives,and once those 3 objectives are done, JIP.sqf should give 4 objectives more...

We tested this mission with a friend of my yesterday, and the first 3 objectives worked well, but when the next set of objectives should have come, i didn't recieve them, and my friend DID, so this somehow seems to mean that the script thinked that im a dedicated server then?

I changed the mission a bit and i now have a trigger that check (= true) conditions from the first 3 objectives like

obj1 && obj2 && obj3

and on the same triggers "on activation" i have

if (isServer) then {first_round_done=true; publicvariable "first_round_done"}

, but it still won't give me new set of objectives when i test this in editor.

Im going crazy with this because im not sure when the script is written so that it only works properly on dedicated server, and when it works for client server. I try to use http://www.ofpec.com/tutorials/index.php?action=show&id=44&page=9 to help me understand all this but its for armed assault and i don't know if this can help me as much as other people.

Would be great if someone could post your own JIP.sqf (NOT USED FOR DEDICATED) script here or send it to my hotmail so i could compare it to my, because i learn much better by checking it that way =)

Share this post


Link to post
Share on other sites

Would be great if someone could post your own JIP.sqf (NOT USED FOR DEDICATED) script here or send it to my hotmail so i could compare it to my, because i learn much better by checking it that way =)

You just have to execute the code from the publicVariableEventhandlers on the host "server" too.

The difference between a hosted environment and a dedicated environment is that in a hosted environment the host is server and client at once. addPublicVariableEventhandler doesn't get fired where the publicVariable command gets executed so you have to run the code from those handlers on the host "server" too.

Concerning JIP, it's totally easy (it really is, no kidding).

Basically all you have to do is to update a JIP client to what allready happened in the mission.

This mostly means update markers, add or change tasks.

What I allmost never do is to change those things (markers) or write some text ( hints, sidechat, whatever) in a trigger activation field simply because when a client joins all those triggers get activated again.

That's why I use isServer &&... in trigger condition fields and then publicVariable a variable which tells all clients that something happened and that they have to react to it, mainly done with addPublicVariableEventhandler (JIP clients simply check such a variable and set things to the correct state when they connect, no chat or hint commands executed then).

Make use of setMarkerXXXLocal instead of setMarkerXXX. The difference is that setMarkerXXXLocal changes markers only on one client and contrary to setMarkerXXX it doesn't get transfered over the network.

Try to learn what locality in MP means. That's allmost the most important part. Understand why things have to be run on the server only or on a client only.

Xeno

Share this post


Link to post
Share on other sites

Sorry! Forgot to mention that i DID use isServer &&... first, but when it didn't seem to work i tried If (isServer) THEN {...

I made a test mission where i blow up 2 trucks (Task1) , and the next objective should become active (blow up 2 x uaz), but nothing =( .

Task1 gets completed, but it won't change it to green in the tasklist...

Something doesn't work here. I could send the example mission to you xeno if you could see what is the problem?

Share this post


Link to post
Share on other sites

try an if statement like this one:

if (isServer || (isServer && !isnil player)) then { code...}

the first is Server checks for dedicated server, the and statement looks for a hosted server where a player exists.

Share this post


Link to post
Share on other sites

Tried this

if (isServer || (isServer && !isnil player)) then {code}

but got message "inil: type object, expected string, code"

=/

Share this post


Link to post
Share on other sites

if (isServer || (isServer && isplayer)) then {code}

got message: Unexpected )

xD

Share this post


Link to post
Share on other sites
i_am_a_server = false;
i_am_a_client = false;
player_initialized = false;
if (isServer) then {
   i_am_a_server = true;
   if (!isDedicated) then {
       // either we are in SP/editor or in a hosted environment
       i_am_a_client = true;
       [] spawn {
           waitUntil {!isNull player};
           player_initialized = true;
       };
   };
} else {
   // I'm a client but the player object may not be initialized yet
   i_am_a_client = true;
   [] spawn {
       waitUntil {!isNull player};
       player_initialized = true;
   };
};

Xeno

Share this post


Link to post
Share on other sites

This goes to a init.sqf?

do i replace this code from the original:

X_INIT = false;
X_Server = false; X_Client = false; X_JIP = false;X_SPE = false;

X_MP = isMultiplayer;

if (isServer) then {
X_Server = true;
if (!(isNull player)) then {X_Client = true;X_SPE = true;};
X_INIT = true;
} else {
X_Client = true;
if (isNull player) then {
	X_JIP = true;
	[] spawn {waitUntil {!(isNull player)};X_INIT = true};
} else {
	X_INIT = true;
};
};

Because if i do i can't see tasks nor notes =)

Share this post


Link to post
Share on other sites

I am attempting to make a JIP.sqf, and this is both the first time I've trie to use one AND I am very fuzzy on sqf format.

I have tried to adapt Xeno's example to my own needs. I have a map in which each player receives a score as the game proceeds. I would like that score to be reset to 10000 when they JIP.

Will this butcher-job syntax work?

i_am_a_server = false;
i_am_a_client = false;
player_initialized = false;

if (player==General) then {
   Wgencash=10000;
   publicvariable "Wgencash";
       };
   };
} else {
   // I'm a client but the player object may not be initialized yet
   i_am_a_client = true;
   [] spawn {
       waitUntil {!isNull player};
       player_initialized = true;
   };
};

if (player==WENG) then {
   WENGcash=10000;
   publicvariable "Wengcash";
       };
   };
} else {
   // I'm a client but the player object may not be initialized yet
   i_am_a_client = true;
   [] spawn {
       waitUntil {!isNull player};
       player_initialized = true;
   };
};

if (player==pilot1) then {
   WPIL1cash=10000;
   publicvariable "Wpil1cash";
       };
   };
} else {
   // I'm a client but the player object may not be initialized yet
   i_am_a_client = true;
   [] spawn {
       waitUntil {!isNull player};
       player_initialized = true;
   };
};

if (player==w1) then {
   W1cash=10000;
   publicvariable "W1cash";
       };
   };
} else {
   // I'm a client but the player object may not be initialized yet
   i_am_a_client = true;
   [] spawn {
       waitUntil {!isNull player};
       player_initialized = true;
   };
};

Edited by Impavido

Share this post


Link to post
Share on other sites

JIP = (!isServer && isNull player);

if (JIP) then {
 [] spawn {
   waitUntil {!isNull player};
   ...do whatever needs to be done for jip...
 };
};

Share this post


Link to post
Share on other sites
JIP = (!isServer && isNull player);

Forgive my poor SQF syntax knowledge but I want to make sure I follow this part:

The above code essentially defines JIP as a variable that becomes TRUE if the client is not the server and the player slot chosen is empty.

Then the following part waits until the slot is filled.

Am I correct in this?

Share this post


Link to post
Share on other sites
Forgive my poor SQF syntax knowledge but I want to make sure I follow this part:

The above code essentially defines JIP as a variable that becomes TRUE if the client is not the server and the player slot chosen is empty.

Yes, it's basically: if (not server and player unit hasnt initialized yet) then jip=true else jip=false

Then the following part waits until the slot is filled.

Am I correct in this?

Yep, it spawns (creates a new thread/process, since waiting inside init.sqf isn't always a good thing) that waits for the player unit to initialize before doing anything, that is to make sure there is an unit to exec commands for.

Share this post


Link to post
Share on other sites
The above code essentially defines JIP as a variable that becomes TRUE if the client is not the server and the player slot chosen is empty.

The code checks that the player is Joining in Progress instead of being present at mission start, difference being that the JiP player is not yet "in game" before the initialization scripts start, whereas a player present at mission start is "in game" during initialization phase.

Therefore, there's a whole moment during JiP process where the function "player" will return objNull even though init scripts are running.

That's the way to detect if a player is JiP or not.

Now, that have another impact : if your normal init scripts (not the ones dedicated to JiP, but the normal init.sqf and scripts spawned from there) are using at any time the function "player" (to retrieve player's name, or class, or side, for example), they will fail for JiP players because function "player" returns objNull. So you may have to wait for player to return a valid object even in your usual init scripts

Share this post


Link to post
Share on other sites

Thanks for the clarification shk and whisper.

---------- Post added at 10:05 PM ---------- Previous post was at 09:51 PM ----------

Oh, and this is a minor detail evading me:

JIP.sqf is run on the server automatically when a player connects?

Share this post


Link to post
Share on other sites

JIP.sqf is not run automatically, you have to run it yourself, from the init.sqf mainly, after having checked that the player is JiP (otherwise, you don't launch JIP.sqf ;) )

A very handy snippet by Sickboy :

http://community.bistudio.com/wiki/6thSense.eu:EG#Determining_if_machine_is_Ingame_Server.2C_Ded_Server.2C_Player_or_JIP_Player. (I'd advise you to carefully read the whole page, a few times, btw ;) )

This will set a few variables which will tell if the current PC where the init.sqf is running on is a server, dedicated or not dedicated, or a client present from start or JiP, all in one :)

This, in turn, means that JIP.sqf launched this way is launched only on the PC of the JiPing player! It is made mainly to fix all the annoying things that are not synchronized automatically when a player join in progress. that means 2 things mainly in arma2 : marker state changes (color, position, text, etc...) after mission start, are not synchronized, and tasks updates are not synchronized either.

To execute a script on server upon player connection, use onPlayerConnected statement in the init.sqf for example.

Edited by whisper

Share this post


Link to post
Share on other sites

Since A2, you can use setVariable / getVariable for JIP, quite efficient, add a Function module to your mission (iniside editor) and add a initJIPCompatible.sqf at your mission root, then you can just add a waitUntil{_var = object getVariable "varName";!isNil "_var"}, it's one of the most efficient way to get a quick JIP.

Quick Ex:

An object or a logic is placed in editor, the variable is assigned to it.

//--- A place is captured by allies.
//--- Object setVariable [Variable Name, Value, Broadcasted].
//--- Server sided.
myLogic setVariable["markerColor","ColorGreen",true];

initJIPcompatible.sqf is ran whenever a player connect.

Player lambda join.

//--- initJIPCompatible.sqf ---//
//--- local to the client.
_var = "";
waitUntil {_var = myLogic getVariable "markerColor";!isNil "_var"};
_marker setMarkerColorLocal _var;

Edited by Benny.

Share this post


Link to post
Share on other sites

should it be:

onplayerconnected [] exec "JIP.sqf"

or

onplayerconnected "[] exec ""JIP.sqf"""

Share this post


Link to post
Share on other sites

use this :)

onPlayerConnected "[] execVM 'JIP.sqf'"
Edited by kju

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×