Jump to content
PYL

Function returns nothing instead of array

Recommended Posts

Hello, I've got the following in-line function:

fnc_test = {
               private ["_a","_b","_c","_d"];
               _a = _this select 0;
               _b = _this select 1;
               _cx = cos(_a);
               _cy = sin(_a);
               _cz = _cx * _cy;
               _cx2 = cos(_b);
               _cy2 = sin(_b);
               _cz2 = _cx2 * _cy2;
               _c = [_cx,_cy,_cz];
               _d = [_cx2,_cy2,_cz2];
               [_c,_d]
           };

To call it I run:

_one = ([_delta, _tetha] call fnc_test) select 0;
_two = ([_delta, _tetha] call fnc_test) select 1;
hintSilent format ["Vec. One: %1 \nVec. Two: %2 \nV.O. Type: %3 \nV.T. Type: %4", _c, _d, typeName _c, typeName _d]; 

With the final script being:

_delta = 45;
_tetha = 45;

_one = ([_delta, _tetha] call fnc_test) select 0;
_two = ([_delta, _tetha] call fnc_test) select 1;

hintSilent format ["Vec. One: %1 \nVec. Two: %2 \nV.O. Type: %3 \nV.T. Type: %4", _c, _d, typeName _c, typeName _d];

fnc_test = {
               private ["_a","_b","_c","_d"];
               _a = _this select 0;
               _b = _this select 1;
               _cx = cos(_a);
               _cy = sin(_a);
               _cz = _cx * _cy;
               _cx2 = cos(_b);
               _cy2 = sin(_b);
               _cz2 = _cx2 * _cy2;
               _c = [_cx,_cy,_cz];
               _d = [_cx2,_cy2,_cz2];
               [_c,_d]
           };

The output is:

Vec. One: any
Vec. Two: any
V.O. Type:
V.T. Type:

Instead of:

Vec. One: [0.7071067812,0.7071067812,0.5]
Vec. Two: [0.7071067812,0.7071067812,0.5]
V.O. Type: ARRAY
V.T. Type: ARRAY

Does somebody know why?

Thanks and have a nice day!

 

P.S. I always run my test scripts in the local exec editor (the one when you press Escape)

Edited by PYL

Share this post


Link to post
Share on other sites

Hi all! Good news! (at least for me :) )

I tried to rewrite the script from scratch and now it works a little bit better: the first run of the script returns nothing, while the afterwards ones give the expected result!

 

Here it is:

_angleone = 45;
_angletwo = 45;

_arrayone = ([_angleone, _angletwo] call my_test_fnc) select 0;
_arraytwo = ([_angleone, _angletwo] call my_test_fnc) select 1;

hintSilent format ["ARRAY ONE: %1 \nARRAY TWO: %2 \nARRAY ONE TYPE: %3 \nARRAY TWO TYPE: %4",_arrayone,_arraytwo,typeName _arrayone,typeName _arraytwo]; 

my_test_fnc = {
                  private ["_ao","_at","_arrayone","_arraytwo"];
	          _ao = _this select 0;
                  _at = _this select 1;
                  _xone = cos(_ao);
                  _yone = sin(_ao);
                  _zone = cos(_ao)*sin(_ao);
                  _xtwo = -cos(_ao);
                  _ytwo = -sin(_ao);
                  _ztwo = -(cos(_ao)*sin(_ao));
                  _arrayone = [_xone,_yone,_zone];
                  _arraytwo = [_xtwo,_ytwo,_ztwo];
                  [_arrayone,_arraytwo]
              };

Is there a fix to make it work from the first run?

And most importantly, why does it behave this strange way?
Cheers!

Edited by PYL

Share this post


Link to post
Share on other sites

Define the function before you call it, not after. ;)

 

Also, you should enable showscriptterrors if you plan to do any kind of scripting.

  • Like 1

Share this post


Link to post
Share on other sites

Define the function before you call it, not after. ;)

 

Also, you should enable showscriptterrors if you plan to do any kind of scripting.

Hi, thanks for the reply! I'm going to test it now. I already enabled -showScripttErrors but the game simply didn't output anything!

Thank you very much really!!! This solved a lot of non-working function errors I had! Now, if I want to make it a standalone function instead of an in-line function, is this the best and/or only way to do so?

 

1. Create a file called "my_test_fnc.sqf" in my VR test mission folder with the above lines of code;

2. In init.sqf (or in my case directly in local exec) type: my_test_fnc = preProcessFile "my_test_fnc.sqf";

3. To call the function, in init.sqf or local exec, type: _result = ([_angleone, _angletwo] call my_test_fnc) select 0 (or 1).
 
Am I correct?Is this the best/fastest way to do so?
Thank you again :P
Edited by PYL

Share this post


Link to post
Share on other sites

Setup:

init.sqf:

my_test_fnc = compileFinal preprocessFileLineNumbers "functs.sqf";

functs.sqf:

params ["_ao", "_at", "_xone", "_yone", "_zone", "_xtwo", "_ytwo", "_ztwo", "_arrayone", "_arraytwo"];
_xone = cos(_ao);
_yone = sin(_ao);
_zone = cos(_ao)*sin(_ao);
_xtwo = -cos(_ao);
_ytwo = -sin(_ao);
_ztwo = -(cos(_ao)*sin(_ao));
_arrayone = [_xone,_yone,_zone];
_arraytwo = [_xtwo,_ytwo,_ztwo];
[_arrayone,_arraytwo];

exec from somewhere:

_angleone = 45;
_angletwo = 45;
_arrayone = ([_angleone, _angletwo] call my_test_fnc) select 0;
_arraytwo = ([_angleone, _angletwo] call my_test_fnc) select 1;

Return:

[0.707107,0.707107,0.5]
[-0.707107,-0.707107,-0.5]
  • Like 1

Share this post


Link to post
Share on other sites

 

your latest code is returning for me :

[0.707107,0.707107,0.5],[-0.707107,-0.707107,-0.5]

Yes but from the second iteration on. Thanks to Greenfist it works since the first, as it should, simply because I learned you have to put your functions before the actual code, if they are inline functions. :)

Share this post


Link to post
Share on other sites

 

Setup:

init.sqf:

my_test_fnc = compileFinal preprocessFileLineNumbers "functs.sqf";

functs.sqf:

params ["_ao", "_at", "_xone", "_yone", "_zone", "_xtwo", "_ytwo", "_ztwo", "_arrayone", "_arraytwo"];
_xone = cos(_ao);
_yone = sin(_ao);
_zone = cos(_ao)*sin(_ao);
_xtwo = -cos(_ao);
_ytwo = -sin(_ao);
_ztwo = -(cos(_ao)*sin(_ao));
_arrayone = [_xone,_yone,_zone];
_arraytwo = [_xtwo,_ytwo,_ztwo];
[_arrayone,_arraytwo];

exec from somewhere:

_angleone = 45;
_angletwo = 45;
_arrayone = ([_angleone, _angletwo] call my_test_fnc) select 0;
_arraytwo = ([_angleone, _angletwo] call my_test_fnc) select 1;

Return:

[0.707107,0.707107,0.5]
[-0.707107,-0.707107,-0.5]

Thanks for your help david.

What's the difference between declaring only the input variables as I did and all the variables which will be used like you did and private vs params?

(private ["_ao","_at","_arrayone","_arraytwo"]; vs params ["_ao", "_at", "_xone", "_yone", "_zone", "_xtwo", "_ytwo", "_ztwo", "_arrayone", "_arraytwo"];)

Share this post


Link to post
Share on other sites

Basically no difference , but if you use params, you not need to extra define passed variables at destination code.

You can merge all private variables (private for this script) with passed variables into one params array.

Always passed variables first, respecting the order.

  • Like 1

Share this post


Link to post
Share on other sites

One question:

why doesn't this work:

params ["_obj","_dir"];
_dir = getDir (_this select 0); // select "index" because it's the first parameter I pass
_dir

but this does?

params ["_obj","_dir"];
_dir = getDir (_this); // tried removing select "index" and it works..
_dir

Share this post


Link to post
Share on other sites

You need to post the passed variable value to make it more readable.

  • Like 1

Share this post


Link to post
Share on other sites

 

One question:

why doesn't this work:

params ["_obj","_dir"];
_dir = getDir (_this select 0); // select "index" because it's the first parameter I pass
_dir

but this does?

params ["_obj","_dir"];
_dir = getDir (_this); // tried removing select "index" and it works..
_dir

Can we see your input? You're not passing an array to the function.

//function call with an array as input
[1,2,3,4,5] call myFunction;
//inside script _this means whatever was input ([1,2,3,4,5])
//Therefore, (_this select 0) is equal to 1

//function call with a single parameter as input
1 call myFunction;
// _this variable still refers to whatever was input (1)
// (_this select 0) is meaningless because input was not an array, will throw "Generic error in expression" error.

//function call with array containing 1 element as input
[1] call myFunction;
//_this still refers to input. _this == [1]
//(_this select 0) == 1

Hope that helps

  • Like 1

Share this post


Link to post
Share on other sites

You need to post the passed variable value to make it more readable.

 

It was " direction = player call function; "

Think dreadedentity provided me a good explaination :)

Share this post


Link to post
Share on other sites

Hi again! How can I add a custom-made, stand-alone (not bound to a mission) function to the official ArmAIII function library so that I can call it like:

result = [p1,p2,...,pn] call function;

Just like you would do with, let's say:

nil = [getPos player, 0, "B_APC_Wheeled_01_cannon_F", EAST] call BIS_fnc_spawnVehicle;


The function I would like to "make official" is:

//
// 1 - object;
// 2 - true (convert to km/h^2)
//   - false (default, m/s^2)
// example: [(vehicle player), false] call PYL_fnc_acceleration
//

params ["_object","_mskmh","_ret"]

        _object = _this select 0;
        _mskmh = _this select 1;

        _dt = (1/diag_fps);
        _xA = vectorMagnitude (velocity _object);

        sleep _dt;

        _xB = vectorMagnitude (velocity _object);
        _dx = _xB - _xA;
        _ret = _dx/_dt;

        if (isNil _mskmh) then {_mskmh = false;};
        if (_mskmh) then {_ret = _ret * 12960;};

        _ret
        

What is the best way to compile this following BIS template and guidelines to, for example, share with you guys on ArmaHolic?

P.S. do you think is it worth "wasting" computing power to add a variable check like:

if ((typeName _object) == OBJECT) then
{
    // the script above
}
else
{
    ["Wrong variable data type (%1)!!!",(typeName _object)] call BIS_fnc_error;
};

Share this post


Link to post
Share on other sites

I managed to make this Config.cpp file:

class CfgFunctions
{
	class PYL
	{
		class Geometry
		{
			file = "myPath";
			class acceleration {returns the acceleration of an OBJECT;};
		};
	};
};

How do I further proceed so i can finally pack this as a pbo, just like ArmAIII's vanilla functions pbo (functions_f, functions_f_gamma, etc)?

Share this post


Link to post
Share on other sites

Could you explain a little bit more what should be the structure of the folder Addon builder will take the files from? I got this error:

 

Build failed. Result code=1

CfgConvert task failed.

File 

C:\Users\PYL\Desktop\test\Config.cpp, line 5:'/CfgFunctions/PYL/Geometry/acceleration.returns': 't' encountered instead of '='

Config : some input after EndOfFile.

Error reading config file 'C:\Users\PYL\Desktop\test\Config.cpp'

Share this post


Link to post
Share on other sites

Basically no difference , but if you use params, you not need to extra define passed variables at destination code.

You can merge all private variables (private for this script) with passed variables into one params array.

Always passed variables first, respecting the order.

I disagree on this. params not only defines listed names as private variables, it also tries to parse them from _this variable. Although work ok for creating local variables, both param and params are not for this, but for simplifying parsing input arguments (compared to previously (and still) used BIS_fnc_param function). In fact, for variables not passed through _this, it is param and params who does extra work in this code:

params ["_someName1", "_someName2"];

vs. this code:

private ["_someName1", "_someName2"];

Also, if working with arguments passed through _this, there's absolutely no point of redefining them right after params:

params ["_arg0", "_arg1"];
_arg0 = _this select 0; // already done by params!
_arg1 = _this select 1; // already done by params!

So, the best practice is let param and params only work with arguments passed through _this, and define all local variables by private:

params ["_object","_mskmh"];
private ["_ret"];
  • Like 1

Share this post


Link to post
Share on other sites

 

I disagree on this. params not only defines listed names as private variables, it also tries to parse them from _this variable. Although work ok for creating local variables, both param and params are not for this, but for simplifying parsing input arguments (compared to previously (and still) used BIS_fnc_param function). In fact, for variables not passed through _this, it is param and params who does extra work in this code:

params ["_someName1", "_someName2"];

vs. this code:

private ["_someName1", "_someName2"];

Also, if working with arguments passed through _this, there's absolutely no point of redefining them right after params:

params ["_arg0", "_arg1"];
_arg0 = _this select 0; // already done by params!
_arg1 = _this select 1; // already done by params!

So, the best practice is let param and params only work with arguments passed through _this, and define all local variables by private:

params ["_object","_mskmh"];
private ["_ret"];

So the final function would be:

//
// 1 - object;
// 2 - true (convert to km/h^2)
//   - false (default, m/s^2)
// example: [(vehicle player), false] call PYL_fnc_acceleration
//

params ["_object","_mskmh"];
private ["_ret"];

        _dt = (1/diag_fps);
        _xA = vectorMagnitude (velocity _object);

        sleep _dt;

        _xB = vectorMagnitude (velocity _object);
        _dx = _xB - _xA;
        _ret = _dx/_dt;

        if (isNil _mskmh) then {_mskmh = false;};
        if (_mskmh) then {_ret = _ret * 12960;};

        _ret
        

?

And what if the output of the function will not be stored in a local variable? Will I need to include it inside params?

Share this post


Link to post
Share on other sites

And what if the output of the function will not be stored in a local variable? Will I need to include it inside params?

You mean function updating some global variable inside function body? If so, this is bad practice and should be avoided.

Share this post


Link to post
Share on other sites

I meant something like:

accel = (vehicle player) call PYL_fnc_acceleration;

instead of:

_accel = (vehicle player) call PYL_fnc_acceleration;

Share this post


Link to post
Share on other sites

What is going on outside the function does not concern the function itself. So you don't specify outside variables inside the function.

BTW, you don't call your function on object, you call it on array of 2 parameters, see your function description :)

BTW2. See params biki page; you can use false as default value for _mskmh parameter and omit this line entirely:

if (isNil _mskmh) then {_mskmh = false;};

BTW3. isNil takes string argument. so must be (isNil "_mskmh")

  • Like 1

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

×