Jump to content
Sign in to follow this  
bad benson

open source function: nearestModels

Recommended Posts

hey folks,

i've had a little night session trying to figure something out and now that i got something that works i want to share it and ask for help optimising it.

as some of you might know it is possible to find map objects (placed in visitor as opposed to the editor) feeding "nearestobjects" with an empty array instead of a classname.

like this:

_list = nearestobjects [player,[],20];

now the thing is that by using that empty array instead of a classname you lose a very important feature of the "nearestobjects" command which is the ability to filter for certain classes and their child classes. this on one hand doesn't matter since the objects i'm searching for here don't have a class name anyways on the other hand it makes the command much more ineffective since now the resulting array contains literally everything except clutter (and forest trees i think). that means honeybees, dragonflies, road parts etc. .

i created a function that searches the entries created by "nearestobjects" for a specific model name and puts those that contain it into a new array. the syntax and the output of the function is basicly the same as the normal "nearestobjects".

_wells = [player,"misc_well.p3d",800] call BaBe_func_NearestModel;

_ref = _this select 0;

_model = _this select 1;

_radius = _this select 2;

_found = [];

_search = nearestobjects [_ref, [], _radius];

{

_object = _x;

_str = str (_object);

_hits = [];

_array = toArray _str;

_num = (_array find 58)+2;

_mnarray = [];

_add = 0;

while {_add < ((count _array) - _num)} do

{

_mnarray = _mnarray + [_array select (_num + _add)];

_add = _add + 1;

};

if ((toString _mnarray) != (_this select 1)) then {}

else

{

_found = _found + [_object];

};

} foreach _search;

_found;

and a version for more than one type:

_wellsNbees = [player,["honeybee.p3d","misc_well.p3d"],800] call BaBe_func_NearestModels;

_ref = _this select 0;

_models = _this select 1;

_radius = _this select 2;

_found = [];

_select = 0;

_search = nearestobjects [_ref, [], _radius];

while {_select < (count _models)} do

{

{

_object = _x;

_str = str (_object);

_hits = [];

_array = toArray _str;

_num = (_array find 58)+2;

_mnarray = [];

_add = 0;

while {_add < ((count _array) - _num)} do

{

_mnarray = _mnarray + [_array select (_num + _add)];

_add = _add + 1;

};

if ((toString _mnarray) != (_models select _select)) then {}

else

{

_found = _found + [_object];

};

} foreach _search;

_select = _select +1;

};

_found;

my methods are really simple and i'm sure leave room for alot of improvement. so maybe some of you script gurus have some ideas how to make this more effective. excuse any weirdness, messiness or noobness. this is basicly my first function and i'm pretty new to this. so be gentle :o

here's an example mission for testing. you'll notice quite a performance hit as soon as you increase the search radius. this is caused by what i described before.

http://www.sendspace.com/file/6k859i

Edited by Bad Benson
download link updated

Share this post


Link to post
Share on other sites

Hi mate...

I got a "cannot play this mission blah blah blah...."

Seems I need something called "babe_inf" in order for the mission to run. You might want to remove that so people without it can try this out.

Share this post


Link to post
Share on other sites

oops. sorry:o some addon i'm working on. it's an easy fix inside the mission.sqm. but anyways. here you go:

------------------------------------------------- (check first post for the right link)

Edited by Bad Benson

Share this post


Link to post
Share on other sites

Hi mate... Hope you don't mind but I shortened it a bit for you. You don't need that outer loop because of the bold stuff below.

Also check out how things are added to the arrays _found and _mnarray. This is more efficient.

_ref = _this select 0;
_models = _this select 1;
_radius = _this select 2;

_found = [];

_select = 0;

_search = nearestobjects [_ref, [], _radius];

{
_object = _x;
_str = str (_object);

_hits = [];
_array = toArray _str;
_num = (_array find 58)+2;
_mnarray = [];
_add = 0;

while {_add < ((count _array) - _num)} do {
   _mnarray set [count _mnarray, _array select (_num + _add)];
   _add = _add + 1;
};

if ([b](toString _mnarray) in _models[/b]) then {
	_found set [count _found,_object];
};

} foreach _search;

_found

Only looked at the function for multiple objects... because you really only need one function. You just call it with one item in the array if you only have one item.

EDIT: Should have added that you handled the strings well. That can be a brain teaser.

Edited by twirly
Clarity

Share this post


Link to post
Share on other sites

wow! that was quick. i'm too tired to try to understand it now but i'm happy you took some intrest in it and actually made it better already. thanks alot!

Share this post


Link to post
Share on other sites

ok. i had another look and got it now. great addition. i guess i should learn some more basic array handling commands before i take the long way again ;)

one last thing. i think the...

_hits = [];

...can be removed. it was the old "_found" and i forgot to remove it. i don't think it really makes a difference but i thought i note that so people don't get confused.

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  

×