Jump to content
Sign in to follow this  
Fiddi

Find near positions.

Recommended Posts

So I need a script that gets nearby positions in a certain radius.

 

The positions is in an array [[0,0,0],[1,1,1]...] like so. And I have a random position, but I need to get an array of the nearby positions.

 

Is there a simple way to do this? I don't want to have to place dummy objects that snatch performance.

 

Thanks.

Share this post


Link to post
Share on other sites


private _pos = [position player, position tank, getMarkerPos "BaseMarker"];

private _rad = 100; //radius

private _rel = _pos apply {_x getPos [random _rad, random 360]}; // random positions around given origins

Share this post


Link to post
Share on other sites

Or you want number of random positions around single origin? Then:

private _org = position player; // origin
private _rad = 100; // radius
private _cnt = 50; // random positions count
private _res = []; // result here

while {_cnt > 0} do {
    _cnt = _cnt - 1; _res pushBack (_org getPos [random _rad, random 360])};

Share this post


Link to post
Share on other sites
private _pos = [position player, position tank, getMarkerPos "BaseMarker"];
private _rad = 100; //radius
private _rel = _pos apply {_x getPos [random _rad, random 360]}; // random positions around given origins

 

I think you misunderstood me (or I you), I have a already defined random position, from which I want to choose one, within radius, between a pre-defined array of positions. Similar to nearobjects.

 

 

What I want is what nearObjects does but with positions [0,0,0] instead. So switch the classnames/type with an array of positions instead that I already have

Share this post


Link to post
Share on other sites

Then:

Fn_SelectPositionNear = {
	params ["_all", "_org", "_rad"];
	selectRandom (_all select {_x distance _org <= _rad})};

[_positions, _origin, _radius] call Fn_SelectPositionNear;
  • Like 2

Share this post


Link to post
Share on other sites

Thanks for the help. I don't really know where to start though, I'm having a bit of a brainfart.
 
Thing is, I've placed hundreds of woodpiles all over Tanoa. Those define my positions and direction, I then in init.sqf I have this:

SideOpPosArray = [];
{
	SideOpPosArray pushBack [getPos _x, getDir _x];
	deleteVehicle _x;
} forEach (allmissionObjects "Land_WoodenPile_F"); 

 
And I have my super large array of positions and directions. Then this function is run whenever I want to start a side mission:

/*
	Author: 
		Fredrik Eriksson
	
	Description: 
		Generates missions and opens the strategic map.
	
	Parameters:
		0 : OBJECT 
				- Calling player.

	Returns:
		NOTHING
*/
params [["_unit", objNull, [objNull]]];
AISkillSideOps = (paramsArray select 6)/10;
_totalMissionArray = [];
_missionPosArray = [];
_mapHalf = worldSize/2;
_minDistance = SideOpDistance; // 3000
_counter = 0;

_nameFirst = [
	"Armed",  "Banned", "Barking", "Black", "Blazing", "Blue", "Brave", "Broken", "Borp", "Burning", "Courageous", 
	"Covered", "Crappy", "Crazy", "Crimson", "Drowned", "Enduring", "Fearful", "Fiery", "Final", "Firing", "Flaming", 
	"Fragging", "Green", "Handle", "Hardened", "Homing", "Hunting", "Killing", "Last", "Lightning", "Lone", 
	"Masterful", "Mobile", "Mourning", "Overwhelming", "Purple", "Qwek", "Raging", "Red", "Retaliating", "Retired", 
	"Rightful", "Rushing", "Ruthless", "Screaming", "Shitty", "Sleeping", "Smashing", "Smoking", "Striking", 
	"Surviving", "Sweeping", "Swift", "Thrusting", "Yellow"
];
_nameSecond = [
	"Angel", "Anvil", "Arrow", "Assault", "Blade", "Boar", "Bolt", "Borp", "Bronze", "Cannon", "Chieftain", 
	"Claw", "Cleaver", "Cobra", "Copper", "Crusader", "Dagger", "Dart", "Devil", "Dragon", "Eagle", "Falcon", 
	"Fist", "Force", "Freedom", "Ghoul", "Gladius", "God", "Grave", "Guardian", "Hammer", "Hawk", "Iron", 
	"Juitttth", "Knight", "Lance", "Lion", "Marauder", "Nightmare", "Nova", "Onslaught", "Paladin", "Phoenix", 
	"Piss", "Poltergeist", "Qwek", "Rage", "Raven", "Rhino", "Rodent", "Sabre", "Shark", "Shield", "Shiet", 
	"Spirit", "Star", "Steel", "Sun", "Switchblade", "Sword", "Swordfish", "Talon", "Thunder", "Trident", 
	"Vengeance", "Viper", "Warlock", "Warrior", "Witch", "Wolf", "Wraith"
];

startLoadingScreen [""];
while {_counter < 6} do {
	_foundSafePos = [[_mapHalf,_mapHalf], 0,_mapHalf,3,0,0.5,0] call BIS_fnc_findSafePos;
	_foundDistAway = true;
	_distanceArray = [];

	{_distanceArray pushBack (_x distance _foundSafePos)} forEach _missionPosArray;
	if ({_x < _minDistance} count _distanceArray > 0) then {_foundDistAway = false};

	if (_foundSafePos distance _unit > _minDistance && {_foundDistAway} && {_foundSafePos distance HQ_dropOff < worldSize}) then {
		_counter = _missionPosArray pushBack _foundSafePos;
		call {
			if (_counter isEqualTo 0) exitWith { // MISSION RESCUE
				_radius = 150;
				Case0MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case0MissionPos = _foundSafePos;
				publicVariable "Case0MissionPos";
				publicVariable "Case0MissionName";

				_missionArray = [
					(Case0MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case0MissionPos, AISkillSideOps, Case0MissionName] remoteExec ["FRED_fnc_Case0Rescue", 2]},
					Case0MissionName,
					"A friendly patrol has been ambushed and requires assistance in the area.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\Stamina_OverEncumbrance_CA.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (1/8);
			};
			if (_counter isEqualTo 1) exitWith { // MISSION STEAL
				_radius = 150;
				Case1MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case1MissionPos = _foundSafePos;
				publicVariable "Case1MissionPos";
				publicVariable "Case1MissionName";
				
				_missionArray = [
					(Case1MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case1MissionPos, AISkillSideOps, Case1MissionName] remoteExec ["FRED_fnc_Case1Steal", 2]},
					Case1MissionName,
					"An enemy truck full of supplies is located somewhere in this area. Locate the truck and bring it back to base safely.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\Driving_ca.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (2/8);
			};
			if (_counter isEqualTo 2) exitWith { // MISSION TARGET
				_radius = 175;
				Case2MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case2MissionPos = _foundSafePos;
				publicVariable "Case2MissionPos";
				publicVariable "Case2MissionName";
				
				_missionArray = [
					(Case2MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case2MissionPos, AISkillSideOps, Case2MissionName] remoteExec ["FRED_fnc_Case2Target", 2]},
					Case2MissionName,
					"Our intel has reported a high value target around this area. Find him and kill him.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\Annoucning_ca.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (3/8);
			};
			if (_counter isEqualTo 3) exitWith { // MISSION DESTROY
				_radius = 300;
				Case3MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case3MissionPos = _foundSafePos;
				publicVariable "Case3MissionPos";
				publicVariable "Case3MissionName";
				
				_missionArray = [
					(Case3MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case3MissionPos, AISkillSideOps, Case3MissionName] remoteExec ["FRED_fnc_Case3Destroy", 2]},
					Case3MissionName,
					"A major military infrastructure has been detected around this area. Locate and destroy it.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\IEDs_ca.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (4/8);
			};
			if (_counter isEqualTo 4) exitWith { // MISSION PILOT
				_radius = 175;
				Case4MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case4MissionPos = _foundSafePos;
				publicVariable "Case4MissionPos";
				publicVariable "Case4MissionName";
				
				_missionArray = [
					(Case4MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case4MissionPos, AISkillSideOps, Case4MissionName] remoteExec ["FRED_fnc_Case4Pilot", 2]},
					Case4MissionName,
					"One of our aircraft has been downed somewhere around this position. Find the pilot and bring him back to base.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\ActionMenu_ca.paa", 
					1,
					[]
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (5/8);
			};
			if (_counter isEqualTo 5) exitWith { // MISSION SABOTAGE
				_radius = 150;
				Case5MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case5MissionPos = _foundSafePos;
				publicVariable "Case5MissionPos";
				publicVariable "Case5MissionName";
				
				_missionArray = [
					(Case5MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case5MissionPos, AISkillSideOps, Case5MissionName] remoteExec ["FRED_fnc_Case5Sabotage", 2]},
					Case5MissionName,
					"We have intel on a sensitive piece of equipment in this area, locate and sabotage it.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\Mines_CA.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (6/8);
			};
			if (_counter isEqualTo 6) exitWith { // MISSION PICKUP
				_radius = 150;
				Case6MissionName = format ["Operation %1 %2",(selectRandom _nameFirst), (selectRandom _nameSecond)];
				Case6MissionPos = _foundSafePos;
				publicVariable "Case6MissionPos";
				publicVariable "Case6MissionName";
				
				_missionArray = [
					(Case6MissionPos getPos [random _radius, random 360] select [0,2]),
					{[Case6MissionPos, AISkillSideOps, Case6MissionName] remoteExec ["FRED_fnc_Case6Transport", 2]},
					Case6MissionName,
					"There's a container who needs transport back to base at this location. A heavy-duty helicopter is needed.",
					"",
					"\a3\ui_f\data\gui\cfg\hints\HookingUp_ca.paa"
				];
				_totalMissionArray pushBack _missionArray;
				progressLoadingScreen (7/8);
			};
		};
	};
};    
endLoadingScreen;

[(findDisplay 46),getpos _unit,_totalMissionArray,[],[],[],0.5,if (daytime > 20 OR daytime < 6) then {true} else {false}, 1, true] call FRED_fnc_strategicMapOpen; 

 

 

That's the previous version which just finds random positions, but it doesn't find positions inside the jungle on Tanoa which is what I want, would be cool.

I want to adapt it to the predefined position while at the same time not spawn two missions within 3000m of each other.

 

Would be so great if it worked, and I'm not being crazy to think it would. The jungle warfare could begin for real if it did. :)

Share this post


Link to post
Share on other sites

Probably just replace your first _foundSafePos with serena's code?

Fn_SelectPositionNear = {
	params ["_all", "_org", "_rad"];
	selectRandom (_all select {_x distance _org <= _rad})};

_foundSafePos = [SideOpPosArray, [_mapHalf, _mapHalf], _mapHalf] call Fn_SelectPositionNear;

Share this post


Link to post
Share on other sites

 Those define my positions and direction, I then in init.sqf I have this:

 

This script is too big and scary, I give up. Hope my function will be useful

  • Like 1

Share this post


Link to post
Share on other sites

 

Probably just replace your first _foundSafePos with serena's code?

Fn_SelectPositionNear = {
	params ["_all", "_org", "_rad"];
	selectRandom (_all select {_x distance _org <= _rad})};

_foundSafePos = [SideOpPosArray, [_mapHalf, _mapHalf], _mapHalf] call Fn_SelectPositionNear;

 

Yes, I'm trying that now, or a variation of it. I keep the findSafePos. And that will be my orig pos. However, I'm stuck yet again. The "SideOpPosArray" is structured like this:

 [  [pos,dir], [[0,0,0],0] ]

And I'm not sure how to modify the function to account for that. 

 

Edit: I might have got it right, I don't know, hard to test until I have modifed the rest of the script.

This is what I came up with:

Fn_SelectPositionNear = {
	params ["_posArray", "_origPos", "_radius"];
	selectRandom (_posArray select {_x select 0 distance _origPos <= _radius})
};

Share this post


Link to post
Share on other sites

Another question, or I'm atleast wondering. How big can an array get without causing problems?

Is there a ceiling for how many elements it can have?

I'm asking because when I'm done there'll be 800-900 locations I have placed and all of them have to insert their position and direction into the array.

 

Also with such a big array, how performance "un-friendly" will a selectRandom be?

Share this post


Link to post
Share on other sites

I'm asking because when I'm done there'll be 800-900 locations I have placed and all of them have to insert their position and direction into the array.

 

Also with such a big array, how performance "un-friendly" will a selectRandom be?

 

I think you'll be fine:

 

 

 

From Arma 3 v1.55.133789 arrays are limited to maximum of 9,999,999 (sometimes 10,000,000) elements

Share this post


Link to post
Share on other sites

I think you'll be fine:

 

Great, then I don't have to hold back on the locations. 1 000 000 locations within 100Km2, here I come! :D

 

I'm so sick of the wood piles in the editor. 

Share this post


Link to post
Share on other sites

Another question, or I'm atleast wondering. How big can an array get without causing problems?

Is there a ceiling for how many elements it can have?

I'm asking because when I'm done there'll be 800-900 locations I have placed and all of them have to insert their position and direction into the array.

 

Also with such a big array, how performance "un-friendly" will a selectRandom be?

 

idk the limit for an array but it should be nearly infinite or dependend on machines RAM.

 

ur selectRandom question:

serenas code selects all positions below the radius before selectRandom is used. so its not used for all positions but for those within the radius.

Share this post


Link to post
Share on other sites

idk the limit for an array but it should be nearly infinite or dependend on machines RAM.

 

ur selectRandom question:

serenas code selects all positions below the radius before selectRandom is used. so its not used for all positions but for those within the radius.

 

Yes, I solved it by first selectRandom on all of the locations and then another, like Serena's code, choosing within the radius. Not sure why I did that but it works.

Share this post


Link to post
Share on other sites

Who not just use lightweight solution with selectBestPlaces or findEmptyPosition instead of predefined positions, monstrous arrays and tons of wood pillars?

 

 

I've tried them, but in the dense jungle of Tanoa those commands can't find any good locations, always end up in a field. And I want it to be able to spawn in the jungle and cities. Also in logical areas, not in the middle of the road.

Share this post


Link to post
Share on other sites

One more, hopefully final, question how do I write such a long array to a file? So I can remove the woodpiles from the mission and just have the positions

 

 

I've tried copyToClipboard and diag_log but they don't write the entire array.

Share this post


Link to post
Share on other sites

diag_log a few values at a time?  Join with , in your favorite text editor.

 

Or UnitCapture as you walk around the island then take that resulting file and remove out the frames where you weren't over the spots you wanted, edit it into array and tada!

  • Like 1

Share this post


Link to post
Share on other sites

diag_log a few values at a time?  Join with , in your favorite text editor.

 

Or UnitCapture as you walk around the island then take that resulting file and remove out the frames where you weren't over the spots you wanted, edit it into array and tada!

 

Yep, that did it I think. Thank you :)

 

Did this:

{
	diag_log _x;
} forEach SideOpPosArray;

879 Lines, and copied over from the log file.

 

Now to just put them in a file and put the return value in a variable on mission start.

Share this post


Link to post
Share on other sites

Using Notepad++ you can alt-drag just the positions from the log.  Then cut and paste and use Edit -> Column Editor to append a comma onto the end of each line.  Easy array!

  • Like 1

Share this post


Link to post
Share on other sites

Using Notepad++ you can alt-drag just the positions from the log.  Then cut and paste and use Edit -> Column Editor to append a comma onto the end of each line.  Easy array!

 

Yes, that's what I did. Though I ran a macro on my keyboard to add commas, I don't know how to use the Column editor.

Share this post


Link to post
Share on other sites


copyToClipboard str (allMissionObjects "Land_WoodPile_F" apply {getPos _x apply {round _x}});

// Result in clipboard: [[11430,11572,0],[11446,11585,0],[11461,11584,0]]

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  

×