Jump to content
Sign in to follow this  
davidoss

Helpme please with function

Recommended Posts

Hi

I have created a function which selecting a road position  and returns it.

fnc_getRoadpos = {

params ["_position", "_radius", "_vehicle"];

_size = sizeOf _vehicle /2;
_roads = _position nearRoads _radius;
_allpos = [];

	for "_i" from 0 to (count _roads) -1 do {

		_topos = getPosATL (_roads select _i);
		_allpos pushback _topos;
	};
	
	_return = selectRandom _allpos;
		
_return
};	

exec is :

_mypos = [getpos player, 500, "C_Offroad_01_F"] call fnc_getRoadpos ;

It works and there is more that should be because i need to include some (if not empty) position future, 

which should select another random position from  _allpos  array.

 

I have messing around with :

_fnc_pickUpEmpty = {
	
		_anchor = selectRandom _allpos;
                _return = selectRandom _allpos;
		_list = _return nearEntities [["Man", "Air", "Car", "Motorcycle", "Tank"], _size];
		if ((_anchor distance _return) < 10) exitWith {false};
		if ((count _list) > 0) exitWith {false};
		if ((count _list) == 0) exitWith {true};
	};

But no luck. Please help.

Share this post


Link to post
Share on other sites

What is the desired end result?

Pick up two random positions from the list, satisfying specified conditions (min distance 10m, no vehicles near second position).

 

Hold on, I'll be back with code.

Share this post


Link to post
Share on other sites

I am using SHK_pos as standard positioning system. Thanks to this I am not crazy yet.

But if i spawn CSAT using it and than Civilian unit and vehicles its going to madness because on relatively small  urbanized area SHK pickups the same positions on each calls

In result CIV vehicles blowup and civilians are run over by a tank.

 

I am trying to avoid this by spawning civs in different way.

Share this post


Link to post
Share on other sites

Ok, here's what I ended up with.

	_fnc_pickUpEmpty = {
		scopeName "_pickUpEmpty";
		private "_apCount";
		_apCount = count _allpos;
		if (_apCount < 2) then {
			false breakOut "_pickUpEmpty";
		};
		private ["_notVisited", "_notVisitedA", "_nvCountA", "_i", "_idxA"];
		_notVisited = [];
		_notVisited resize _apCount;
		for [{i=0}, {i < _apCount}, {_i=_i+1}] do {
			_notVisited set [_i, _i];
		};
		_notVisitedA = +_notVisited;
		_nvCountA = _apCount;
		while {_nvCountA > 0} do {
			// picking up first/anchor position
			_i = floor random _nvCountA;
			_idxA = _notVisitedA select _i;
			_anchor = _allpos select _idxA;
			_notVisitedA deleteAt _i;
			_nvCountA = _nvCountA - 1;

			private ["_notVisitedR", "_nvCountR", "_k", "_idxR"];
			_notVisitedR = +_notVisited;
			_notVisitedR deleteAt _idxA; // filtering out anchor position
			_nvCountR = _apCount-1;
			while {_nvCountR > 0} do {
				// picking up second/return position
				_k = floor random _nvCountR;
				_idxR = _notVisitedR select _k;
				_return = _allpos select _idxR;
				_notVisitedR deleteAt _k;
				_nvCountR = _nvCountR - 1;
				if ((_anchor distance _return) >= 10) then {
					_list = _return nearEntities [["Man", "Air", "Car", "Motorcycle", "Tank"], _size];
					if ((count _list) == 0) then {
						true breakOut "_pickUpEmpty";
					};
				};
			};
		};
		false
	}; 

BTW, your fnc_getRoadpos function may return nil (if roads are too far, then _roads stays empty and _allpos stays empty too), make sure you handle this case (like, I dunno, increasing _radius or so).

 

UPD, sorry forgot about min distance, edited.

Share this post


Link to post
Share on other sites

Amazing but i am confused how i can use your code can you help?

Share this post


Link to post
Share on other sites

Amazing but i am confused how i can use your code can you help?

Place it right where your _fnc_pickUpEmpty inline function was defined -- on the same scope where _allpos, _anchor_return and _size variables were declared, but before first use of function. Possible usage:

if (call _fnc_pickUpEmpty) then {
  // successfully placed
  // ... do something
} else {
  // could not find placement
  // ... do something else
}; 

If you decide to make function not inline, don't forget you will need to return not only true/false status, but also updated _anchor and _return values (updated automatically in inline variant).

Share this post


Link to post
Share on other sites

Hi,

 

Don't know if it will help you in future but...

 

BIS_fnc_arrayShuffle is what you are searching for,

 

Instead of picking random element - deleting that element from the array - picking another random element what you do is to reorganise randomly the same array and picking a sequence of elements in a for, foreach or whatever method.

 

Is what I use in my civ spawn script for the parked cars, I have a DB with road positions and I reorganise it everytime the function is activated, so I won't use the same position twice and everytime the position will be different.

Share this post


Link to post
Share on other sites

Sorry but.. this is giving me nothing , i need to knew how to implement that.

I knew how to find road and get its position far away i see only darkness.

Share this post


Link to post
Share on other sites

Ok

 

You have your roads array, and want to use let's say 5 positions, random ones.

 

_roads = _position nearRoads _radius;

 

_roads = _roads call BIS_fnc_arrayShuffle; // now you have it reordered with elements in random order

 

for "_i" from 0 to 5 do

{

_road = _roads select _i;

_veh = createVehicle ["C_Offroad_01_F", position _road, [], 0, "NONE"];

};

 

Share this post


Link to post
Share on other sites

Instead of picking random element - deleting that element from the array - picking another random element what you do is to reorganise randomly the same array and picking a sequence of elements in a for, foreach or whatever method.

If it only were to pick two random position, then yes. But how about checking conditions for picked locations?

Imagine you have a list of 50 locations. You can pick 50 location for the first one and 49 for the second. Since different conditions applied to first and second location, same location make up a different pair if in reverse order, i.e. [pos1, pos2] is not the same as [pos2, pos1]. Therefore you have a full set of 50x49=2450 possible pairs to check. Now imagine only one combinations fits all conditions. You can shuffle the array for quite a long time until right combination appears in right place. Whereas my variant never checks the same pair again.

Share this post


Link to post
Share on other sites

can you please prepare full function? i cant make it  working.  After calling it make arma unresponsive and crash.

I have something wrong.

Share this post


Link to post
Share on other sites

I put very bad desing into this function, I'm very sorry. I had costly operation nearEntities called at each _return position overwhelming amount of times, much more than it was needed.

Now I fix my mistake:

	_fnc_pickUpEmpty = {
		scopeName "_pickUpEmpty";
		private "_apCount";
		_apCount = count _allpos;
		if (_apCount < 2) then {
			false breakOut "_pickUpEmpty";
		};
		private ["_notVisited", "_notVisitedR", "_nvCountR", "_i", "_idxR"];
		_notVisited = [];
		_notVisited resize _apCount;
		for [{i=0}, {i < _apCount}, {_i=_i+1}] do {
			_notVisited set [_i, _i];
		};
		_notVisitedR = +_notVisited;
		_nvCountR = _apCount;
		while {_nvCountR > 0} do {
			// picking up second/return position
			_i = floor random _nvCountR;
			_idxR = _notVisitedR select _i;
			_return = _allpos select _idxR;
			_notVisitedR deleteAt _i;
			_nvCountR = _nvCountR - 1;
			private ["_notVisitedA", "_nvCountA", "_k", "_idxA", "_list"];
			_notVisitedA = +_notVisited;
			_notVisitedA deleteAt _idxR; // filtering out return position
			_nvCountA = _apCount-1;
			while {_nvCountA > 0} do {
				// picking up first/anchor position
				_k = floor random _nvCountA;
				_idxA = _notVisitedA select _k;
				_anchor = _allpos select _idxA;
				_notVisitedA deleteAt _k;
				_nvCountA = _nvCountA - 1;
				if ((_anchor distance _return) >= 10) then {
					if (isNil "_list") then {
						_list = _return nearEntities [["Man", "Air", "Car", "Motorcycle", "Tank"], _size];
					};
					if ((count _list) == 0) then {
						true breakOut "_pickUpEmpty";
					};
				};
			};
		};
		false
	};

Now nearEntites should not be called more than once for every _return position.

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  

×