Jump to content
Blitzen88

How can I delete “extra” units after an Array has been Resized?

Recommended Posts

Good morning,

 

I’m having some trouble figuring out how to delete “extra” units after an array has been resized.  Here is what I got


 

if (count _SquadUnits > count _TrenchPos) then { _SquadUnits resize (count _TrenchPos) };


//Delete "Extra" Units

_SquadUnitsToDelete = _TrenchGroup - _SquadUnits;

 

{deletevehicle _x } foreach _SquadUnitsToDelete;

 

Basically, I want to delete “extra” units so that the number of SquadUnits is equal to the number of Trenchpos.

Share this post


Link to post
Share on other sites

Good evening. It would be nice to look at the contents of both arrays in the example, then it will be possible to understand whether you are trying to act correctly.

  • Like 1

Share this post


Link to post
Share on other sites
28 minutes ago, Ibragim A said:

Good evening. It would be nice to look at the contents of both arrays in the example, then it will be possible to understand whether you are trying to act correctly.

/*==========================================================================================

 

                                                                Arma III - Trench WIP

 

Created by Blitzen

 

===========================================================================================

 

* Blah

 

* Parameters:

    

                - SquadLeader: Trench group's squadleader

 

                - Radius: Search radius for defined object (trench position)

 

* Call with: [This, 200, "Sign_Arrow_Blue_F"] execVM "Scripts\AI\AI_Trench.sqf"

 

===========================================================================================*/

 

//Define Input Variables

 

_SquadLeader = _this select 0;

 

_Radius = _this select 1;

 

_TrenchPosObject = _this select 2;

 

//Create Variables that will be used by the script

 

_TrenchUnits = units group _Squadleader;

 

//Get Trench Positions and shuffle the array

 

_TrenchPositions = getpos _SquadLeader nearObjects [_TrenchPosObject, _Radius];

 

_TrenchPositions = _TrenchPositions call BIS_fnc_arrayShuffle;

                

//If there are more units than positions then resize the units array and delete "extra" units

 

if (count _TrenchUnits > count _TrenchPositions) then {

 

                _TrenchUnits = _TrenchUnits resize (count _TrenchPositions);

 

                if !(_x in _TrenchUnits) then {deletevehicle _x} foreach units group _Squadleader;

 

};

 

//Count the squad units for the loop

 

_CountTrenchUnits = count _TrenchUnits; 

 

//Start Loop

 

while {_CountTrenchUnits > 0} do {

 

                //Select the Unit

                _Unit = _TrenchUnits select 0;

 

                //Remove the selected unit from the array

                _TrenchUnits = _TrenchUnits - [_Unit];

                                

                //Select the Trench object

                _SelectedTrenchPosition = _TrenchPositions select 0;

                                

                //Remove the Selected Trench object from the array

                _TrenchPositions = _TrenchPositions - [_SelectedTrenchPosition];

 

                //Get the Object's position - thats what we really want

                _SavedTrenchPosition = getpos _SelectedTrenchPosition;

 

                //Delete the object since we have the object's position saved

                deletevehicle _SelectedTrenchPosition;

                                

                _unit setpos _SavedTrenchPosition;

 

                _unit disableAI "Path";

 

                _unit setUnitPos "Up";

                                

                sleep 1;

 

                //Reduce the SquadUnits Count by 1

                _CountSquadUnit = _CountSquadUnit - 1;

 

//End Loop

};

 

//Delete Remaining positions

if (count _TrenchPositions > 0) then {

 

                {deletevehicle _x} foreach _TrenchPositions;

 

};

Share this post


Link to post
Share on other sites
1 hour ago, Blitzen88 said:

                _TrenchUnits = _TrenchUnits resize (count _TrenchPositions);

The resize command does not return a value, so this line contains an error. Rewrite it like this:

_TrenchUnits resize (count _TrenchPositions);

 

  • Like 2

Share this post


Link to post
Share on other sites
3 minutes ago, Ibragim A said:

The resize command does not return a value, so this line contains an error. Rewrite it like this:


_TrenchUnits resize (count _TrenchPositions);

 

Will do. 
 

Does my deletion of extra units work?

Share this post


Link to post
Share on other sites

I only looked at the part of the code you asked the question for and did not see any other errors in it.

Share this post


Link to post
Share on other sites

Variables containing arrays are a reference to an array.  That means when an array gets changed (i.e., resized), all the variables that refer to that array will also see and reflect that change.

_units = units group leader;			// Gets the (units group) array.
_unitsToDelete = _units;			// Both _units and _unitsToDelete now refer to the same array.

_units resize 3;				// Both _units and _unitsToDelete change (they refer to the same array).

_unitsToDelete = _unitsToDelete - _units;	//Both _units and _unitsToDelete become empty; they're the same array.

To prevent a change in one variable from affecting other variables through array reference, you make a copy of the array.

_units = +(units group _leader);		// Makes a separate copy of the (units group) array.
_unitsToDelete = +_units;			// Makes a separate copy of the _units array.

_units resize 3;				// Doesn't effect the _unitsToDelete array by reference.

_unitsToDelete = _unitsToDelete - _units;	// Doesn't effect the _units array by reference.

 

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

You can use also deleteAt command


 

private _units = units group _squadLeader;
private _trenchPositions = getpos _SquadLeader nearObjects [_TrenchPosObject, _Radius];  // I can't check that
private _trenchPositions = _trenchPositions call BIS_fnc_arrayShuffle;             // no need to shuffle each time

{
   if (count _trenchPositions >0) then {
     _pos = getpos (_trenchPositions deleteAt 0);
     _x setpos _pos;
   } else {
     deleteVehicle _x;
   }
} forEach _units

 

  • Like 3

Share this post


Link to post
Share on other sites

Hey there @pierremgi. Nice piece of code there but I have a question... I don't really get the

_x setPos getPos _pos;

line. Isn't _pos already a position? If yes, why should you use getPos again? If not, then what does it contain (since in the previous line you initialise _pos with the result of a getPos command)?

 

This part got me kinda confused... Could you please clarify that?

 

Thanks in advance :).

  • Like 1

Share this post


Link to post
Share on other sites

_trenchPositions are objects extracted by nearObjects. I copied the Blitzen88's code, confused with this name, which is probably a test one with arrows.

Anyway, you're right getPos is for objects and _pos is already a position..

 

Corrected.

  • Like 2

Share this post


Link to post
Share on other sites

Well, I guess that a combination of opusfmspol's and pierremgi's suggestions make a quite nice solution to your problem at hand. It could look something like

// Your code
private _trenchUnits = units group _Squadleader;

// Pierremgi's code
private _units = units group leader;
private _trenchPositions = getpos _SquadLeader nearObjects [_TrenchPosObject, _Radius];
private _trenchPositions = _trenchPositions call BIS_fnc_arrayShuffle;

// Pierremgi's code adapted based on opusfmspol's code
{
	deleteVehicle _x;
} forEach (_trenchUnits - ((+_trenchUnits) resize _trenchPositions));

Not sure this is a good or bad solution but, at least to me, it looks like a quite compact one. It's up to you to decide whether it is OK for you or not and of course the rest of the contributors might have something to add or suggest.

  • Like 1

Share this post


Link to post
Share on other sites
On 10/19/2021 at 3:18 PM, Blitzen88 said:

Good morning,

 

I’m having some trouble figuring out how to delete “extra” units after an array has been resized. 



Like this:

 

_arr = [objNull, objNull, objNull, objNull, objNull]; 
_maxUnits = 3; 
while { count _arr > _maxUnits } do 
{ 
  deleteVehicle (_arr deleteAt (count arr - 1));
}; 
_arr

 

  • Like 3

Share this post


Link to post
Share on other sites

This is what I came up with....seems to work for me:

 

/*==========================================================================================

				Arma III - Trench

Created by Blitzen

===========================================================================================

* Defines "positions" by capturing user placed objects

* Can be used to define defensive positions in a trench/FOB style of fortification

* Script is necessary for units that respawn and need to occupy the same position

* Script will delete "unused" units and will hide unused trench positions

* Parameters:
    
	- SquadLeader: Trench group's squadleader

	- Radius: Search radius for defined object (trench position)

	- Object: Object that is used to identify a trench position (highly recommend the "helper signs (ie arrows) since they dont have collision

* Call with: [This, 200, "Sign_Arrow_Blue_F"] execVM "Scripts\AI\AI_Trench.sqf"

===========================================================================================*/

//Define Input Variables

_SquadLeader = _this select 0;

_Radius = _this select 1;

_TrenchPosObject = _this select 2;

//Create Variables that will be used by the script

_TrenchUnits = units group _Squadleader;

//Get Trench Positions and shuffle the array

_TrenchPositions = getpos _SquadLeader nearObjects [_TrenchPosObject, _Radius];

_TrenchPositions = _TrenchPositions call BIS_fnc_arrayShuffle;

{hideObject _x} foreach _TrenchPositions;

{_x allowDamage false} foreach _TrenchPositions;

if ((Count _TrenchPositions) == 0) exitWith {Player groupChat "Trench Script - No Trench Positions Detected;"};

//Count the Trench units for the loop

_CountTrenchPositions = count  _TrenchPositions;

//Go ahead and disable movement and set unit positions

{_x disableai "path"} foreach _TrenchUnits;

{_x setUnitPos "Up"} foreach _TrenchUnits;

//Start Loop

_Go = True;

while {_Go} do {

	if ((count _TrenchUnits) == 0) exitWith {_Go = False};

	if ((count _TrenchPositions) == 0) exitWith {_Go = False};

	//Select the Unit
	_Unit = _TrenchUnits select 0;

	//Remove the selected unit from the array
	_TrenchUnits = _TrenchUnits - [_Unit];
		
	//Select the Trench object
	_SelectedTrenchPosition = _TrenchPositions select 0;
		
	//Remove the Selected Trench object from the array
	_TrenchPositions = _TrenchPositions - [_SelectedTrenchPosition];

	//Get the Object's position - thats what we really want
	_SavedTrenchPosition = getpos _SelectedTrenchPosition;

	_unit setpos _SavedTrenchPosition;
		
	sleep 1;

	//Reduce the SquadUnits Count by 1
	_CountTrenchPositions = _CountTrenchPositions - 1;

//End Loop
};

if (count _TrenchUnits > 0) then {

	{deletevehicle _x} foreach _TrenchUnits;

};




 


 

  • Like 1

Share this post


Link to post
Share on other sites

As said above, you can use deleteAt command.

It's useless allowing damage false for arrows!

Your loop seems to me convoluted.

 

Exact same result:

 

params ["_SquadLeader","_Radius","_TrenchPosObject"];
private _trenchUnits = units group _Squadleader;
private _trenchPositions = getpos _SquadLeader nearObjects [_TrenchPosObject, _Radius];
private _trenchPositions = _trenchPositions call BIS_fnc_arrayShuffle;
{_x hideObject TRUE} count _TrenchPositions;
{
   if (count _trenchPositions >0) then {
     _pos = getpos (_trenchPositions deleteAt 0);
     _x setpos _pos;
     _x disableai "path";
     _x setUnitPos "Up"
   } else {
     deleteVehicle _x;
   }
} forEach _trenchUnits;

 

  • Like 2

Share this post


Link to post
Share on other sites
On 10/24/2021 at 9:00 AM, pierremgi said:

As said above, you can use deleteAt command.

It's useless allowing damage false for arrows!

Your loop seems to me convoluted.

 

Exact same result:

 

 

Im just not that good at scripting and I try to stick to what I know. I will check out your script and will check out deleteat. 
 

thank you!

  • 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

×