Jump to content
Sign in to follow this  
eymerich

Array, set, do for...

Recommended Posts

This is a code I have written and (of course) it doesn't work.

It is neither being considered worty by my pc.

In any case,

"Arr" is an array storing unit defined by the function "list trigger"

Now, I want Arr be ordered and resized.

/*Code*/

/ take the array and count it's elements

_index = 0;

_loop = count Arr;

// found the unit alive

For [ { _index },{ _index < _loop },{_index = _index + 1}] Do

{

sleep 0.1;

//is the last unit?

If ( ( _index + 1 ) == loop ) Then

{

exitwith {};

};

If ( Not ( Alive ( Arr select _index ) ) ) Then

{

/switch the second unit to the first unit

Arr set [_index, Arr select ( _index + 1) ];

};

};

// now order the array: Arr select 0 must be the nearest unit (in the array) to the player

_index = 0;

_loop = count Arr;

For [ { _index }, { _index < _loop }, { _index = _index + 1 } Do

{

//is the last unit? If yes the loop is finished

sleep 0.1;

If ( (_index + 1 ) == _loop ) Then ExitWith {};

_alfa = ( Arr select _index ) distance player;

_beta = ( Arr select ( _index + 1 ) ) distance player;

//compare the 2 distance

If ( _Beta < _Alfa } Then

{

Arr set [ _index, Arr select ( _index + 1) ];

};

};

The code should be executed by the statement:

_null = execVm ".sqf"

But nothing.

One more question: what's to the line for debug? (-debug?)

Thanks in advance

Share this post


Link to post
Share on other sites

Going to halt reading and ask: was this a direct copypaste?

/switch the second unit to the first unit

/ instead of //

Did you use -showScriptErrors when you launched Arma 3?

Edit: shouldn't have stopped. You asked that in the end. It's -showScriptErrors :)

Share this post


Link to post
Share on other sites

I think this is what the code you posted should look like.

for[{_i=0},{_i<=(count Arr)},{_i =_i+1}] do  {
sleep 0.1;
if(!(alive(Arr select _i))) then {
	Arr set[_i,Arr select (_i+1)];
};
};

for[{ _y=0},{_y<=(count Arr)},{_y = _y+1} do {
sleep 0.1;

_alpha = (Arr select _y) distance player;
_beta = (Arr select(_y+1)) distance player;

if(_beta<_alpha} then {
	Arr set[_y,Arr select (_y+1)];
};
};

A few questions though. What is Arr, because it is undef and can you post the script that is execvming this?

Share this post


Link to post
Share on other sites
I think this is what the code you posted should look like.

for[{_i=0},{_i<=(count Arr)},{_i =_i+1}] do  {
sleep 0.1;
if(!(alive(Arr select _i))) then {
	Arr set[_i,Arr select (_i+1)];
};
};

for[{ _y=0},{_y<=(count Arr)},{_y = _y+1} do {
sleep 0.1;

_alpha = (Arr select _y) distance player;
_beta = (Arr select(_y+1)) distance player;

if(_beta<_alpha} then {
	Arr set[_y,Arr select (_y+1)];
};
};

A few questions though. What is Arr, because it is undef and can you post the script that is execvming this?

Thanks all for helping me.

Arr is a global variable (global array) defined in a trigger in the editor.

It's filled with soldiers inside the trigger and defined by the statement: Arr = List Trigger1, where "Trigger1" is the name of the trigger.

My code is... s**t... :mad:

In any case, i think it's wrong under a different prospective.

The comparison of distance should follow this logic:

Arr set[0, Arr select (_y)];

I need only the first element which have to be the nearest object to player compared to the other.

Edit ---

Please consider this:

for[{_i=0},{_i<=(count Arr)},{_i =_i+1}] do {

sleep 0.1;

if(!(alive(Arr select _i))) then {

Arr set[_i,Arr select (_i+1)];

};

};

Let's say there are 5 elements in the array.

What's happen if _i = 5 in this line of code:

Arr set[ 5, Arr select ( 5+1)]

Edited by Eymerich

Share this post


Link to post
Share on other sites

If there are 5 elements in the array then 'Arr select 5' is out of bounds (oddly called 'error zero divisor' in ArmA). Array indexes start at 0 for the first element; count command starts at 1 for the first element, because the count of an empty array is 0. I would recommend this:

http://community.bistudio.com/wiki/forEach

There are only a few cases in which it is preferable to use a for loop to iterate on arrays. I get the vague sense that you are trying to order each object in the array based upon its distance from the player. Under that assumption, I would do it like this:

/*
   Reorders the elements of the given array into a new array based
   upon their distance from a single center object
   Params: 1. Object, the center
           2. Array of objects
   Return: Array of objects
*/
private ["_unit", "_givenArray", "_sortedArray", "_nextObj"];
_unit = _this select 0;
_givenArray = _this select 1;
_sortedArray = [];

{
   _nextObj = _givenArray select 0;
   {
       if (((_x distance _unit) < (_nextObj distance _unit)) && {(!(_x in _sortedArray) && (alive _x))}) then {_nextObj = _x;};
   } forEach _givenArray;
   if !(_nextObj in _sortedArray) then {
       _sortedArray set [(count _sortedArray), _nextObj];
   };
} forEach _givenArray;
_sortedArray

I accounted for the objects being alive, as you seem to want that; that code should remove all dead objects from the array. This is tested and working with objects around the player in the editor, some of them dead. Just define it as a function with any name you want and call it like so:

Arr = [player, Arr] call <FunctionName>;

Share this post


Link to post
Share on other sites
_sortedArr = [ARR, [], {player distance _x}, "ASCEND", {alive _x}] call BIS_fnc_sortBy;

Share this post


Link to post
Share on other sites

First of all, Thanks to you all.

Depending on how it sorts things you might just use nearEntities or just nearestObjects looking for "Men" (which sorts by distance automatically) instead of reinventing the wheel.

Well, you know: i wouldn't miss the taste of "the first time" :)

In any case, nearest object and nearentities doesn't fit for me cause they'll get my mate (player is in a team of 3\4 men) and not the enemy: so i need to start with an array "builded" by a trigger: in short, I "List" the kind of unit i need (resistence side) to create the array i need.

(At least: I don't know a different way to do this; suggestions or tips are Always more than welcome)

/*

Reorders the elements of the given array into a new array based

upon their distance from a single center object

Params: 1. Object, the center

2. Array of objects

Return: Array of objects

*/

private ["_unit", "_givenArray", "_sortedArray", "_nextObj"];

_unit = _this select 0;

_givenArray = _this select 1;

_sortedArray = [];

{

_nextObj = _givenArray select 0;

{

if (((_x distance _unit) < (_nextObj distance _unit)) && {(!(_x in _sortedArray) && (alive _x))}) then {_nextObj = _x;};

} forEach _givenArray;

if !(_nextObj in _sortedArray) then {

_sortedArray set [(count _sortedArray), _nextObj];

};

} forEach _givenArray;

_sortedArray

_sortedArr = [ARR, [], {player distance _x}, "ASCEND", {alive _x}] call BIS_fnc_sortBy;

I'll Have a try and I'll report.

Edit--

The code worked like a charm!

One more question, a bit off topic but i prefer ask here to avoid to create different thread.

If I have to call a function, I use the statement "call" --> game is stopped, the function is executed and i get the value; okay.

If I have to exec a script I use the statement [] exec ".sqs" --> no problem for me.

What is the different beetwen exec "sqs", exec "sqf" and execVm ".sqf"?

When I have to operate on a global variable, do i have to pass it to the script (_null = [globalvariable] execvm ".sqf") or I can use that variable inside the script without passing it (_null = execVm ".sqf"; just like I did with the sqs script - [] exec "...sqs")?

Edited by Eymerich

Share this post


Link to post
Share on other sites

One more question, a bit off topic but i prefer ask here to avoid to create different thread.

If I have to call a function, I use the statement "call" --> game is stopped, the function is executed and i get the value; okay.

If I have to exec a script I use the statement [] exec ".sqs" --> no problem for me.

What is the different beetwen exec "sqs", exec "sqf" and execVm ".sqf"?

When I have to operate on a global variable, do i have to pass it to the script (_null = [globalvariable] execvm ".sqf") or I can use that variable inside the script without passing it (_null = execVm ".sqf"; just like I did with the sqs script - [] exec "...sqs")?

The 'exec' command is used with sqs syntax, which is deprecated. All functions should be written in sqf syntax, and 'exec' should not be used to call sqf scripts, only 'execVM'. The 'execVM' command compiles and executes the script as a new thread and passes in arguments. You can also use 'spawn' to execute a function as a new thread.

A global variable is defined for all functions for the entire mission, unless it is removed with 'nil'. Any function can access and modify a global variable; it does not have to be passed as a argument. In multiplayer, a global variable is defined on all machines that was declared on, but the value does not sync between them nor is it transferred to other machines. You must use 'publicVariable' to do that.

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  

×