Jump to content
Sign in to follow this  
iceman77

MP compatability

Recommended Posts

Hi.I've just recently started learning how to script.I've visited the wiki and spent hours learning new things. I have been working on a coop mission and I wanted to make sure it was multiplayer compatible.ie, JIP and locality of scripts/functions.Mainly im just trying to learn here, so I set up this small mission (wich works as intended in the editor)so I can better understand, SP and/or MP SQF syntax structure.Any constructive, accurate feedback is surely welcomed here.Iam looking for opinions/advice on the code structure I used so I can be more efficient.

How the mission works:

The mission is quite small/simple really. I have 3 objects pre-placed on the map via editor that have to be eliminated (dead). 2 igla AA pods & 1 radar station. They are each named accordingly- stat1,stat2 and stat3.Also each one gets a marker on the map, marker names = aa1,aa2 and aa3.Whenever I eliminate anyone of the 3 objectives I get a hint message telling me i've eliminated x# out of 3 AA pods(objectives) bla bla bla, and also it deletes the corrosponding objective/destroy marker for each objective neutralized. In my mission folder I have the mission.sqm,init.sqf,folder named "missions",in "missions" folder are 4 sqf files. mission1.sqf, marker1.sqf,marker2.sqf, and marker3.sqf.

Heres how iam currently doing it:

init.sqf

[] execVM "missions\mission1.sqf";//call the script that checks if objectives are alive
["Takistan", "2016", "Pestilence Rain"] spawn BIS_fnc_infoText;//beggining text

mission1.sqf

//AA sabo mission Objective check

[] execVM "missions\marker1.sqf";
[] execVM "missions\marker2.sqf";
[] execVM "missions\marker3.sqf";

waituntil {{alive _x} count [stat1,stat2,stat3] == 2};
_objective1 = if ({alive _x} count [stat1,stat2,stat3] == 2) then {"1/3 Objectives completed"} else {""};
hint str _objective1;


waituntil {{alive _x} count [stat1,stat2,stat3] == 1};
_objective2 = if ({alive _x} count [stat1,stat2,stat3] == 1) then {"2/3 Objectives completed"} else {""};
hint str _objective2;


waituntil {{alive _x} count [stat1,stat2,stat3] == 0};
_objective3 = if ({alive _x} count [stat1,stat2,stat3] == 0) then {"3/3 Objectives completed"} else {""};
hint str _objective3;

sleep 5;

["Mission", "Complete"] spawn BIS_fnc_infoText;

marker1.sqf

waituntil {{alive _x} count [stat1] == 0};
_objective1 = if ({alive _x} count [stat1] == 0) then deletemarker "aa1";

marker2.sqf

waituntil {{alive _x} count [stat2] == 0};
_objective2 = if ({alive _x} count [stat2] == 0) then deletemarker "aa2";

marker3.sqf

waituntil {{alive _x} count [stat3] == 0};
_objective3 = if ({alive _x} count [stat3] == 0) then deletemarker "aa3";

So, that's it. What can I do to ensure that it will run well as a MP map on a dedicated server with mabey some people JIP? I would like to ensure that JIP players are caught up with the rest of the server in terms of marker deletion and objective completion etc etc.

Also, mabey this isn't the best/easiest/most efficient way to set this up via scripts, any tips would be great.I realize my code structure and how I set things up in the files must be ludicrous.

PS, mabey i could use eventhandlers to delete the markers? idk

Teach me :bounce3:

Edited by Iceman77

Share this post


Link to post
Share on other sites

I have some general and specific comments.

Since you are executing mission1.sqf from the init.sqf, and you have not used any limiters (e.g. isServer, isDedicated, etc), it will run on all clients and the server. Your markerx.sqf scripts will also run on all clients and the server since they are in turn executed from mission1.sqf. Having all of your scripts running on all machines can be good or bad...it depends on what you are trying to achieve. In theory, if there is no reason to run a script on all machines, you should not.

So, in the case of your mission, if you are hoping to achieve that all machines know when an objective has been completed and shows a hint (to players only since the server does not get hints), then it should work. I think JIP players should also be properly updated when they join based on your code. They are some scripting irregularities to be fixed, but I will cover that below. More importanly is to focus on effeciency and avoiding conflicting information.

As an alternative and perhaps more resource effecient way of achieveing your goal, you could set up a system by which only the server runs mission1.sqf, so you have one central monitoring of the status of your objectives, and then broadcast changes to the clients for them to delete the markers. This would avoid having multiple waitUntil loops running on all of your machines. This can be done with public variable events handlers (PVEH), the MP framework (I know, I know), or through CBA functions or other similar methods. If you are just starting out, PVs and PVEHs are the best starting point (at least to learn) and then decide if you need a more advanced solution.

An additional alternative would be to use triggers for most of what you want to achieve which would most likely simplify everything.

So regarding code ireregularities, I recommend the following edits:

You can drasticaly simplyfing mission1.sqf to this:

//AA sabo mission Objective check

[] execVM "missions\marker1.sqf";
[] execVM "missions\marker2.sqf";
[] execVM "missions\marker3.sqf";

private {"_objectives"];

_objectives = [stat1,stat2,stat3];

waituntil {{alive _x} count _objectives == 2};
hint "1/3 Objectives completed";

waituntil {{alive _x} count _objectives == 1};
hint "2/3 Objectives completed";

waituntil {{alive _x} count _objectives == 0};
hint "3/3 Objectives completed";

sleep 5;

["Mission", "Complete"] spawn BIS_fnc_infoText;

There is no point re-typing code if you do not have to.

Your marker scripts can also be reduced to this (change as needed):

//marker1.sqf

waituntil {!alive stat1};
deleteMarker "aa1";

I have to run now, but I can give you some more guidance later (and I am sure others will chime in). In the meantime be sure to read these:

http://community.bistudio.com/wiki/6thSense.eu:EG

http://www.ofpec.com/tutorials/index.php?action=show&id=44

You can also drastically simplify all of your mission if you eliminate the "1/3 objectives" complete messages and just send messages that a specific objective has been completed instead of how many have been complete.

Share this post


Link to post
Share on other sites

Cool, thanks alot for the reply. Why/what is the Private command? And I see you assigned stat1,stat2,stat3 to _objectives variable. The variables are what iam confused on, local, public, global etc..when and where to use certain ones and for what.

Share this post


Link to post
Share on other sites

Here is a link to a couple of Biki articles on private and scope, but essentially, you use it to ensure that so that a variable is available throughout your whole script, even deeper scopes. For your scripts it is probably not a big issue since you are not changing the value of _objectives inside your waitUntil blocks, but it ensures that _objectives is accessible in each of those deeper scopes. It is good practice to declare all of your local variables that you want available throughout your script using the private command.

Here is a article section that discusses the differnence between local, global, and public variables. To quote it:

Local - A variable is only visible in the script in which it was defined.

Global - A variable is visible on the whole computer where it is defined.

Public - A variable is broadcasted over the network and visible on all computers connected to the network.

In quick sum, if you are only need a variable within a script, use a local variable. If you have multiple scripts that might need a script on the same machine, use a global. If you need several machines to have the same variable, use public variables.'

Hope that helps!

Share this post


Link to post
Share on other sites
[Y]ou use [private] to ensure that so that a variable is available throughout your whole script

You don't need to use private for this; you just need to declare the variable somewhere. In this script, for example, "_objectives" has been defined in the main scope, so it will automatically be available in all sub-scopes.

Share this post


Link to post
Share on other sites
You don't need to use private for this; you just need to declare the variable somewhere. In this script, for example, "_objectives" has been defined in the main scope, so it will automatically be available in all sub-scopes.

Thanks for clarifying, I should have chosen my words more carefully. I understand that...I included it in order to establish that overall it is good practive to use private even if not applicable in this instance. While not always necessary and in rare circumstaces probably should not be used...I have found that you will avoid problems (perhaps unforessen ones) by using it then not using it.

Here is a recent thread that goes deeper into the use of private:

variables in loops and scope?

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  

×