Fiddi 68 Posted June 15, 2016 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
serena 151 Posted June 15, 2016 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
serena 151 Posted June 15, 2016 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
kylania 568 Posted June 15, 2016 Wouldn't you want to use https://community.bistudio.com/wiki/BIS_fnc_findSafePos otherwise you could be spawning things in inside walls and trees and whatnot? Share this post Link to post Share on other sites
Fiddi 68 Posted June 15, 2016 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
kylania 568 Posted June 15, 2016 Maybe a check against syntax 3 of inArea or a simple loop checking for distance2D of your spots? Share this post Link to post Share on other sites
serena 151 Posted June 15, 2016 Then: Fn_SelectPositionNear = { params ["_all", "_org", "_rad"]; selectRandom (_all select {_x distance _org <= _rad})}; [_positions, _origin, _radius] call Fn_SelectPositionNear; 2 Share this post Link to post Share on other sites
Fiddi 68 Posted June 15, 2016 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
kylania 568 Posted June 15, 2016 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
serena 151 Posted June 15, 2016 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 1 Share this post Link to post Share on other sites
Fiddi 68 Posted June 15, 2016 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
Fiddi 68 Posted June 16, 2016 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
kylania 568 Posted June 16, 2016 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
Fiddi 68 Posted June 16, 2016 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
sarogahtyp 1108 Posted June 16, 2016 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
Fiddi 68 Posted June 16, 2016 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
serena 151 Posted June 16, 2016 Who not just use lightweight solution with selectBestPlaces or findEmptyPosition instead of predefined positions, monstrous arrays and tons of wood pillars? Share this post Link to post Share on other sites
Fiddi 68 Posted June 16, 2016 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
Fiddi 68 Posted June 16, 2016 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
kylania 568 Posted June 16, 2016 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! 1 Share this post Link to post Share on other sites
Fiddi 68 Posted June 16, 2016 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
kylania 568 Posted June 16, 2016 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! 1 Share this post Link to post Share on other sites
Fiddi 68 Posted June 16, 2016 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
serena 151 Posted June 17, 2016 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