Jump to content
draugar

Trying to find closest object behind player vehicle

Recommended Posts

I have been working on this for a week now and have not been able to work out a solution.  I want to find the closest vehicle behind my vehicle.  I want it to first see if there is a vehicle in the area of 6m behind player vehicle.  If it finds one (it may find more than one) I want it to choose the closest.  If it doesn't, then I want to see if there is a vehicle in the area of 8m and choose the closest.  And so on with 10m.  If it doesn't find any vehicles after these three tests, then I want it to give me the hint.  I am able to get the tow function to work, but I think it is only using the 10m setting because that is the last one in the array.  If you haven't guessed already, I'm new to scripting.


_towpos = {vehicle player modelToWorld _x} forEach [[0,-6,0],[0,-8,0],[0,-10,0]];
_near = nearestObjects [(_towpos), ["Car","Truck","Motorcycle"], 2];
_near = _near - [vehicle player];

if (count _near < 1) exitwith {
hint "There are no towable vehicles nearby!";
};

_nearest = _near select 0;

*edited for formatting
Edited by draugar

Share this post


Link to post
Share on other sites

You have to do all your checking in the foreach loop else all it is doing is returning the last modelToWorld position being -10 into _towpos.

Something like..

_towvehicle = {
    _pos = vehicle player modelToWorld [0,_x,0];
    _near = nearestObjects [ _pos, ["Car","Truck","Motorcycle"], 2];
    _near = _near - [vehicle player];
    if ( count _near > 0 ) exitWith {
        _near select 0
    };
} forEach [-6,-8,-10];


if ( isNil "_towVehicle") then {
    hint "There are no towable vehicles nearby!";
}else{
    hint format [ "There is a %1 ready for towing", typeOf _towVehicle ];
};

So it checks each distance -6,-8 and -10, It turns distance into a world position, checks position for vehicles, makes sure its not the players vehicle and if there is still something left exits the foreach passing the first thing in the list into _towVehicle. If there was nothing found then _towVehicle will be nil.

Share this post


Link to post
Share on other sites

Oh cool. I wanted to allow my bobcat drivers to unflip vehicles by reversing up to them (because the bobcat crane is there). I'm going to use/butcher this snippet to do that, if that's OK. :)

Share this post


Link to post
Share on other sites

Larrow, I think I spoke too soon.  I can't get it to fit correctly into my script:

_veh = _this;
_isTowing = _veh getVariable "isTowing";
if (!isNil "_isTowing") then {
	detach ((vehicle player) getVariable "isTowing");
	// Move 2M back
	_pos = ((vehicle player) getVariable "isTowing") modelToWorld [0,-2,-2];
	_pos = [_pos select 0,_pos select 1,1];
	((vehicle player) getVariable "isTowing") setpos _pos;
	
	((vehicle player) getVariable "isTowing") setVariable ["isBeingTowed",nil,true];
	(vehicle player) setVariable ["isTowing",nil,true];
} else {
	_towVehicle = {
		_towpos = vehicle player modelToWorld [0,_x,0];
		_near = nearestObjects [ _towpos, ["Car","Truck","Motorcycle"], 2];
		_near = _near - [vehicle player];
		if ( count _near > 0 ) exitWith {};
	} foreach [-6,-8,-10];

	if ( isNil "_towVehicle") exitwith {
		["No towable vehicle nearby",20,"red"] call A3L_Fnc_Msg;
	};
	_nearest = _near select 0;
	if ((vehicle player) animationPhase "Tow" > 0.1) exitwith {
		["Towbar is not lowered",20,"red"] call A3L_Fnc_Msg;
	};

	if (locked _nearest > 1) exitwith {
		["This vehicle is locked and cannot be towed",20,"red"] call A3L_Fnc_Msg;
	};

	_isTowed = _nearest getVariable "isTowing";
	_isBeingTowed = _nearest getVariable "isBeingTowed";
	if ((!isNil "_isTowed") OR (!isNil "_isBeingTowed")) exitwith {
		["Vehicle is already being towed or is towing another vehicle",20,"red"] call A3L_Fnc_Msg;
	};

	// Get attachpoint
	_attachpoint = [];
	_lookfor = typeof _nearest;
	{
		if ((_x select 0) == _lookfor) then {
			_attachpoint = _x select 1;
		};
	} foreach A3L_Fnc_TowArray;

	if (count _attachpoint == 0) exitwith {
		["Unable to retrieve vectorpoints for this vehicle",20,"red"] call A3L_Fnc_Msg;
	};

	_nearest attachto [(vehicle player),_attachpoint];
	[[_nearest],"A3L_Fnc_TowtruckVector", true, false] call BIS_fnc_MP;

	(vehicle player) setVariable ["isTowing",_nearest,true];
	_nearest setVariable ["isBeingTowed",true,true];
};

Here is the original script that will allow the tow truck to tow a vehicle that is in front of it, which is what I'm trying to correct:

/*
        File: Tow.sqf
        Author: Caiden
       
        Description:
        Main handler for attempting to tow/untow a vehicle
*/

_veh = _this;
_isTowing = _veh getVariable "isTowing";
if (!isNil "_isTowing") then {
	detach ((vehicle player) getVariable "isTowing");
	// Move 2M back
	_pos = ((vehicle player) getVariable "isTowing") modelToWorld [0,-2,-2];
	_pos = [_pos select 0,_pos select 1,1];
	((vehicle player) getVariable "isTowing") setpos _pos;
	
	((vehicle player) getVariable "isTowing") setVariable ["isBeingTowed",nil,true];
	(vehicle player) setVariable ["isTowing",nil,true];
} else {

	_near = nearestObjects [(vehicle player), ["Car","Truck","Motorcycle"], 10.5];
	_near = _near - [vehicle player];
	
	if (count _near < 1) exitwith {
		["No towable vehicle nearby",20,"red"] call A3L_Fnc_Msg;
	};
	
	if ((vehicle player) animationPhase "Tow" > 0.1) exitwith {
		["Towbar is not lowered",20,"red"] call A3L_Fnc_Msg;
	};
	
	
	_nearest = _near select 0;
	
	if (locked _nearest > 1) exitwith {
		["This vehicle is locked and cannot be towed",20,"red"] call A3L_Fnc_Msg;
	};
	
	_isTowed = _nearest getVariable "isTowing";
	_isBeingTowed = _nearest getVariable "isBeingTowed";
	if ((!isNil "_isTowed") OR (!isNil "_isBeingTowed")) exitwith {
		["Vehicle is already being towed or is towing another vehicle",20,"red"] call A3L_Fnc_Msg;
	};
	
	// Get attachpoint
	_attachpoint = [];
	_lookfor = typeof _nearest;
	{
	if ((_x select 0) == _lookfor) then {
	_attachpoint = _x select 1;
	};
	} foreach A3L_Fnc_TowArray;
	
	if (count _attachpoint == 0) exitwith {
		["Unable to retrieve vectorpoints for this vehicle",20,"red"] call A3L_Fnc_Msg;
	};
	
	_nearest attachto [(vehicle player),_attachpoint];
	[[_nearest],"A3L_Fnc_TowtruckVector", true, false] call BIS_fnc_MP;
	
	(vehicle player) setVariable ["isTowing",_nearest,true];
	_nearest setVariable ["isBeingTowed",true,true];
	
	
};

Share this post


Link to post
Share on other sites

_veh = _this;
_isTowing = _veh getVariable "isTowing";
if (!isNil "_isTowing") then {
	_towed = ((vehicle player) getVariable "isTowing");
	detach _towed;
	// Move 2M back
	_pos = _towed modelToWorld [0,-2,0];
	_pos set [ 2, 1 ];
	_towed setPosATL _pos;
	
	_towed setVariable ["isBeingTowed",nil,true];
	(vehicle player) setVariable ["isTowing",nil,true];
} else {
	_vehToTow = {
		_towpos = vehicle player modelToWorld [0,_x,0];
		_near = nearestObjects [ _towpos, ["Car","Truck","Motorcycle"], 1];
		_near = [ _near, [], { _x distance vehicle player }] call BIS_fnc_sortBy;
		_near = _near - [vehicle player];
		if ( count _near > 0 ) exitWith {
			_near select 0	
		};
	} forEach [-6,-8,-10];

	if ( isNil "_vehToTow") exitwith {
		["No towable vehicle nearby",20,"red"] call A3L_Fnc_Msg;
	};
	
	if ((vehicle player) animationPhase "Tow" > 0.1) exitwith {
		["Towbar is not lowered",20,"red"] call A3L_Fnc_Msg;
	};

	if (locked _vehToTow > 1) exitwith {
		["This vehicle is locked and cannot be towed",20,"red"] call A3L_Fnc_Msg;
	};

	_isTowed = _vehToTow getVariable "isTowing";
	_isBeingTowed = _vehToTow getVariable "isBeingTowed";
	if ((!isNil "_isTowed") OR (!isNil "_isBeingTowed")) exitwith {
		["Vehicle is already being towed or is towing another vehicle",20,"red"] call A3L_Fnc_Msg;
	};

	// Get attachpoint
	_attachpoint = {
		if ((_x select 0) == typeOf _vehToTow) exitWith {
			_x select 1
		};
	} foreach A3L_Fnc_TowArray;

	if (count _attachpoint == 0) exitwith {
		["Unable to retrieve vectorpoints for this vehicle",20,"red"] call A3L_Fnc_Msg;
	};

	_vehToTow attachto [(vehicle player),_attachpoint];
	[[_vehToTow],"A3L_Fnc_TowtruckVector", true, false] call BIS_fnc_MP;

	(vehicle player) setVariable ["isTowing",_vehToTow,true];
	_vehToTow setVariable ["isBeingTowed",true,true];
};
 

Think thats correct. Was playing around with some other code (pasted below) but im pretty sure i removed anything other than fixes. Added a sort function in there just on the off chance a vehicle is closer to the player than the nearObjects center.

Something to play with..

 

player addAction [ "check tow", {
	_towVehicle = vehicle player;
	_towVehiclePos = getPosASL _towVehicle vectorAdd [0,0,0.5];
	_towCheckEndPos = [ _towVehiclePos, -12, getDir _towVehicle ] call BIS_fnc_relPos;
	_objs = lineIntersectsObjs [_towVehiclePos, _towCheckEndPos, _towVehicle, objNull, true, 32];
	reverse _objs;
	_vehToTow = {
		_obj = _x;
		if ( { _obj isKindOf _x }count ["Car","Truck","Motorcycle"] > 0 ) exitWith { _obj };
	}forEach _objs;
	
	if !( isNil "_vehToTow" ) then {
		hint str typeOf _vehToTow;
	}else{
		hint "nothing found";
	};
}];

[ "oef", "onEachFrame", {
	_towVehicle = vehicle player;
	_towVehiclePos = getPosASL _towVehicle vectorAdd [0,0,0.5];
	_towCheckEndPos = [ _towVehiclePos, -12, getDir _towVehicle ] call BIS_fnc_relPos;
	_objs = lineIntersectsObjs [_towVehiclePos, _towCheckEndPos, _towVehicle, objNull, true, 32];
	reverse _objs;
	drawLine3D [ ASLToATL _towVehiclePos, ASLToATL _towCheckEndPos, [ 1, 0, 0, 1 ] ];
}] call BIS_fnc_addStackedEventHandler;

Share this post


Link to post
Share on other sites

This is one of the closet and most recent threads I can relating to my problem. Apologies if this is rude!

 

Is there a way to add a 'buffer' when looking for objects. e.g I don't want the _pos2 to get anything within 1k of the player but everthing else up to 17k away 

_pos2 = nearestLocations [getPos player,["nameCity","nameVillage"],17000]; 

Share this post


Link to post
Share on other sites

you are brilliant.  I had to change a few lines of code as the "vectorpoints" check was not working properly.  It would not tow the vehicle of course, but when I clicked on the addaction "tow/untow" button again it would bump the vehicle, like I was untowing.  Changing the _attachpoint section to a variation of the original fixed it.  See below.

 

from this:

	_attachpoint = {
		if ((_x select 0) == typeOf _vehToTow) exitWith {
			_x select 1
		};
	} foreach A3L_Fnc_TowArray;

to this:

 	_attachpoint = [];
	_lookfor = typeof _vehToTow;
	{
	if ((_x select 0) == typeOf _vehToTow) then {
	_attachpoint = _x select 1;
	};
	} foreach A3L_Fnc_TowArray;

Let me know if you see any concerns.  Also, I have not played with the bonus code yet.

 

Edited to add this:  I just got done playing with the bonus code.  Pretty good stuff.  Especially for testing purposes.  Want to join our dev team?  http://www.arma3-life.com/ :)

Share this post


Link to post
Share on other sites

I have been playing around with both scripts.  I was wondering if there was a way for the "lineIntersectsObjs" command, or some similar command, to look for the "boundingbox" of an object, instead of the object itself?

_towVehicle = vehicle player;
	_towVehiclePos = getPosASL _towVehicle vectorAdd [0,0,0.5];
	_towCheckEndPos = [ _towVehiclePos, -12, getDir _towVehicle ] call BIS_fnc_relPos;
	_objs = lineIntersectsObjs [_towVehiclePos, _towCheckEndPos, _towVehicle, objNull, true, 32];
	reverse _objs;
	_vehToTow = {
		_obj = _x;
		if ( { _obj isKindOf _x }count ["Car","Truck","Motorcycle"] > 0 ) exitWith { _obj };
	}forEach _objs;
	
	if !( isNil "_vehToTow" ) then {
		hint str typeOf _vehToTow;

Share this post


Link to post
Share on other sites

Unfortunately a bounding box is not an entity, it is basically just two points that define the max and min area that an objects vertices are enclosed in, in model space.

Would be nice though if we could do the opposite by casting a basic shape along a ray and return any intersecting objects. For example casting a box of min, max along the length of a ray. I could see many uses for this like as you are trying to find tow objects behind a vehicle, doing a ray intersect could potentially miss a vehicle if the line went under the object. Casting a box along the line could save missing these objects. Could even be used to find safe places to spawn stuff. You could do this via script by casting a set lines but would be faster if an engine based approach was available.

Share this post


Link to post
Share on other sites

Your "Something to play with" script, in post #6, works perfectly on most vehicles.  One vehicle in particular does not return the name of the vehicle unless the red line passes through the middle of the vehicle from the side.  If I try it from the front or back, it returns "found nothing", even though the red line is buried deep into the model.  Any other vehicle I have tried it on, I only have to touch a corner of the visible model to return the name of the vehicle.  I tested the non-working model by putting a visible bounding box around it and it looks normal.  I don't understand why this vehicle is acting that way.  If you can think of any reason why this would be, please share.

 

I also tried the new command "lineIntersectsSurfaces" and it doesn't seem to be working yet.

Share this post


Link to post
Share on other sites

What vehicle?

Share this post


Link to post
Share on other sites

The vehicle I'm referring to is called A3L_Bus.  That is the one that is not working correctly with the script.

Share this post


Link to post
Share on other sites

Because one, or more, of the vehicles is not fully recognized with this script, I would like to take a new approach to this.  I want to return all vehicles within an 8m radius behind the towtruck.

		_towpos = vehicle player modelToWorld [0,-6,-1];
		_near = nearestObjects [ _towpos, ["Car","Truck","Motorcycle"], 8];

 I want to test each vehicle in the array and see if it meets the following criteria:

_dir = [vehicle player, _nearest] call BIS_fnc_relativeDirTo;
_dir >= 160 && _dir <= 200

Finally, I want it to return the nearest vehicle.

I know the sample code is not exactly what I need.  I am not very good with dealing with arrays and the foreach loops.

Share this post


Link to post
Share on other sites

something like....

    _towpos = vehicle player modelToWorld [0,-6,0];
    _near = nearestObjects [ _towpos, ["Car","Truck","Motorcycle"], 8];
    _near = _near - [vehicle player];
    _near = [ _near, [], { _x distance vehicle player }, "ASCEND", { [ _towPos,( getDir vehicle player ) - 180 , 20, getPosATL _x] call BIS_fnc_inAngleSector }] call BIS_fnc_sortBy;
    _vehToTow = _near select 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

×