Jump to content
Sign in to follow this  
Guest

User defined functions in 1.85

Recommended Posts

Guest

1.85 introduces new powerful scripting possibilities through user definable functions. This is implemented through the "call", "loadFile" and the "if-then-else,while-do... etc" functions.

What is the big difference between "call" and the old "exec"? -"call" allows you to return a value. This is imperative in creating larger and more complex scripts.

Here is a code example of a simple implementation of a fuction that adds two matrices. Thanks goes to Suma for the code. I have only made small adjustments to make it work with the 1.85 release syntax.

testm.sqs

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

_matrixA = [ [2,2], [2,2], [2,2],[1,2]]

_matrixB = [ [1,1], [1,1], [1,1],[2,3]]

_result = [_matrixA, _matrixB] call loadFile "matrixAdd.sqf"

titleText[format["Matrix A:%1\nMatrixB:%2\nA+B:%3",_matrixA,_matrixB,_result], "PLAIN",1]

<span id='postcolor'>

matrixAdd.sqf:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

comment

{

     Demonstration of new expression possibilities

     Note: this is not a script, this is single expression

     Script constructs @,~, ? or goto are not possible here.

     Semicolons are strictly required, as end of line has no special meaning

     and is considered as normal space character.

};

comment

{

     All this is implemented using new "while", "if" and "call" functions.

     They are real functions taking string arguments and executing them.

     Brackets {} are very similiar to quotes - expression closed in them

     is string expression.

};

comment "Declare local variables";

private ["_matrixA","_matrixB","_rows","_cols","_diff","_result","_i","_j"];

_matrixA = _this select 0;

_matrixB = _this select 1;

_rows = count _matrixA;

_cols = count (_matrixA select 0);

_result = [];

_i = 0;

comment "Perform calculation in two while loops";

while "_i<_rows" do

{

     

     _j = 0;

     _innerRow = [];

     while "_j<_cols" do

     {

           _diff = ((_matrixA select _i) select _j) + ((_matrixB select _i) select _j);

           _innerRow set [_j, _diff];

           _j =_j + 1;

     };

     

     _result set [_i,_innerRow];

     _i=_i+1;

};

_result

<span id='postcolor'>

Share this post


Link to post
Share on other sites

From the new ComRef:

"Many languague constructs (including forEach, if, while) use concept of "code strings". Code is passed as string to them and they interpret it as code if they wish. Since 1.85 string constants can be written in two ways: using double quotes (like "Hello") or curled braces (like {a=a+1}). While both ways are currently equivalent and string constant is created, we recommend to use curled braces for code only, as this makes scripts easier to read - moreover future versions of scripting language may precompile code enclosed in curled braces."

Precompiling eventually! Suma & BIS - good show!

Prospero

Share this post


Link to post
Share on other sites

Could someone explain to us "normals" what this means? Give us a small example of what can be done please. confused.gif

Share this post


Link to post
Share on other sites

Basicly it lets you create a function (like adding 2 numbers together), using a function can keep scripts small if you are going to use the same function (adding 2 numbers together for example)

For example instead of putting this in your script file, you just call it (like a header file .h in C++) It will keep your scripts neater and a lot easier to read.

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

comment

{

Demonstration of new expression possibilities

Note: this is not a script, this is single expression

Script constructs @,~, ? or goto are not possible here.

Semicolons are strictly required, as end of line has no special meaning

and is considered as normal space character.

};

comment

{

All this is implemented using new "while", "if" and "call" functions.

They are real functions taking string arguments and executing them.

Brackets {} are very similiar to quotes - expression closed in them

is string expression.

};

comment "Declare local variables";

private ["_matrixA","_matrixB","_rows","_cols","_diff","_result","_i","_j"];

_matrixA = _this select 0;

_matrixB = _this select 1;

_rows = count _matrixA;

_cols = count (_matrixA select 0);

_result = [];

_i = 0;

comment "Perform calculation in two while loops";

while "_i<_rows" do

{

_j = 0;

_innerRow = [];

while "_j<_cols" do

{

_diff = ((_matrixA select _i) select _j) + ((_matrixB select _i) select _j);

_innerRow set [_j, _diff];

_j =_j + 1;

};

_result set [_i,_innerRow];

_i=_i+1;

};

_result

<span id='postcolor'>

RED

Share this post


Link to post
Share on other sites

Yeah, and for even more hardcore-scripters there is preprocessFile instead of loadFile!

You may define your own C-like macros in your SQF-files. I've got a sample function pos2grid which converts ofp-position vector [x,y,z] to grid position "Ea64".

create a test.sqs with following content:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

_gridpos = (getpos player) call preprocessFile "pos2grid.sqf"

hint format ["%1", _gridpos]

<span id='postcolor'>

And create pos2grid.sqf:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

#define DIV(_X, _Y) ((_X / _Y) - (_X / _Y) % 1)

#define MOD(_X, _Y) ((_X % _Y) - (_X % _Y) % 1)

private ["_a", "_b", "_result", "_big", "_small", "_num", "_g1", "_g2", "_g3", "_g4"];

_a = _this select 0;

_b = _this select 1;

_big  = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"];

_small = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];

_num   = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];

_g1 = DIV(_a, 1280);

_g2 = DIV( MOD(_a, 1280), 128);

_g3 = DIV(_b, 1280);

_g4 = DIV( MOD(_b, 1280), 128);

_result = format ["%1%2%3%4", _big select _g1, _small select _g2, _num select _g3, _num select _g4];

_result

<span id='postcolor'>

You see that even nested macros are allowed!

Now place some trigger and execute test.sqs! Now the gridpos of your player should be displayed!

Share this post


Link to post
Share on other sites
Guest

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Hovmand @ Oct. 15 2002,13:42)</td></tr><tr><td id="QUOTE">Could someone explain to us "normals" what this means? Give us a small example of what can be done please.  confused.gif<span id='postcolor'>

Example: Function that returns the sum of two numbers:

sum.sqf:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

private ["_a","_b","_sum"];

_a = _this select 0;

_b = _this select 1;

_sum = _a+_b;

_sum

<span id='postcolor'>

And you would call the function like this to get the sum of for example 2 + 3:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

_sum = [2,3] call loadFile "sum.sqf"

<span id='postcolor'>

Share this post


Link to post
Share on other sites
Guest

PreprocessFile allows you to define macros while loadFile expects a clean format.

Share this post


Link to post
Share on other sites

Because in Bigpoppa's example, he's using the preprocess file to use the 'C-like' functionality. The code in his example only works using preprocess, not loadfile. (I'd imagine smile.gif)

tounge.gif PEACE

Share this post


Link to post
Share on other sites

LoadFile is slightly faster, but both of them can be considered slow, as both of them require file access (which is also true for exec).

If you really want something to be fast (which is probably not the case of pos2grid, but may be for some other often executed fuctions), do not do:

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">_gridpos = (getpos player) call preprocessFile "pos2grid.sqf"

hint format ["%1", _gridpos]

<span id='postcolor'>

Preload content of the file to some global variable instead (once, in init.sqs).

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

GridPosFunction = preprocessFile "pos2grid.sqf"

....

_gridpos = (getpos player) call GridPosFunction

<span id='postcolor'>

This way you will avoid reloading and releasing file at each use of the function (at some memory cost).

Share this post


Link to post
Share on other sites

If I do this

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE"> _result =(_Pos) call loadFile "GridCoord.sqf" <span id='postcolor'>

Call execute ONE time and after bugs.

If I do this

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">_result =[_Pos] call loadFile "GridCoord.sqf"<span id='postcolor'>

No bug, why () works one time?

And for OFP scripters without knowledge of C, in sqf you can do this :

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

private ["_result","_GrandeLettre","_PetiteLettre","_Chiffre", "_Chiffrestring","_Pos"];

_Pos = _This select 0;

_Chiffrestring ="";

_result = "";

_GrandeLettre = (((_Pos select 0) - ((_Pos select 0) Mod 1280))/1280);                            

_PetiteLettre =((((_Pos select 0) Mod 1280)- (((_Pos select 0) Mod 1280)Mod 128))/128);  

_Chiffre = (99 - ((_Pos select 1) - ((_Pos select 1) Mod 128))/128);        

_Chiffrestring = Format["%1",_Chiffre];

If (_Chiffre < 10) then  {_Chiffrestring = "0" + _Chiffrestring };

If (_Chiffre != 0) then  {nobody globalchat "Bonjour";nobody globalchat "Au revoir" };

_result = (( ArrayMajuscForGrid select _GrandeLettre) + ( ArrayMinusForGrid select _PetiteLettre) +_Chiffrestring);

_result<span id='postcolor'>

Very near of OFP scripting I think...

Share this post


Link to post
Share on other sites

@uiox

because one time it's an array of array [_pos] and the other it's just an array (_pos)

[_pos] = [ [_x, _y, _z] ]

(_pos) = [_x, _y, _z]

wink.gif

Share this post


Link to post
Share on other sites

OK,

So the right syntax is : [] call gridCoordFunction.

Share this post


Link to post
Share on other sites

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (uiox @ Oct. 16 2002,13:18)</td></tr><tr><td id="QUOTE">So the right syntax is : [] call gridCoordFunction.<span id='postcolor'>

Both syntax is correct. If you will use (_pos) call gridCoordFunction, _this will be _pos. If you will use [_pos] call gridCoordFunction, _this will be [_pos] - make your choice.

Share this post


Link to post
Share on other sites

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Suma @ Oct. 16 2002,12:15)</td></tr><tr><td id="QUOTE">LoadFile is slightly faster, but both of them can be considered slow, as both of them require file access (which is also true for exec).<span id='postcolor'>

I always suspected this from my empirical tests, but many thanks for confirming it, Suma. That's very helpful. I suspect I am correct in saying that calling scripts from the Drop command also depends on file access, and is therefore similarly relatively slow.

Thanks again Suma.

Prospero

Share this post


Link to post
Share on other sites

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Suma @ Oct. 16 2002,12:15)</td></tr><tr><td id="QUOTE">If you really want something to be fast, [edit] preload content of the file to some global variable instead (once, in init.sqs).

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">

GridPosFunction = preprocessFile "pos2grid.sqf"

....

_gridpos = (getpos player) call GridPosFunction

<span id='postcolor'>

This way you will avoid reloading and releasing file at each use of the function (at some memory cost).<span id='postcolor'>

Could I somehow preload a Drop command into a global variable this way?

Prospero

Share this post


Link to post
Share on other sites

Umm, you can't use #define's in a loadFile?? I'm getting

|x|#define FOO ...

when I load the function. I suppose this makes sense (use preprocessfile instead???), but there's no #ifndef #endif stuff.

Maybe this has already been mentioned?? #define does not work with any function you call with loadFile.

Doolittle

Share this post


Link to post
Share on other sites

</span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Quote (Doolittle @ Oct. 22 2002,09:56)</td></tr><tr><td id="QUOTE">#define does not work with any function you call with loadFile.<span id='postcolor'>

#define works with text files (including functions) loaded by preprocessFile.

Share this post


Link to post
Share on other sites

I have question about command private ["_i","_j","_k"].

What that it function?For example,if I delete this

function in pos2grid.sqf(see above),this script been work too.

I'm sorry!I not programmer but I want understand this.

Can Your cite example were this function it is necessary.

sad.gif

p.s.sorry for my english.

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  

×