Jump to content
Sign in to follow this  
TraxusIV

How to identify where a bullet lands

Recommended Posts

I can use a "Fired" event handler to tell when I fire a weapon, but is it possible to identify when and what the bullet hits?

Share this post


Link to post
Share on other sites

You could find the bullet with _this select 6 and then track it in a loop while it's alive:

private ["_bullet", "_last_pos"];

_bullet = _this select 6;

while {alive _bullet} do
{
_last_pos = getPosATL _bullet;	
sleep 0.01;
};

// then return _last_pos and check time once it is "dead"

player sideChat format ["Pos: %1, Time = %2", _last_pos, time];

Untested, let me know if it works. There may be some other way of doing it I'm unaware of.

Edited by Das Attorney
forgot private dec

Share this post


Link to post
Share on other sites

Yeah, we really need an "impact" event handler. Either that or make "killed" event handlers also work on projectiles to detect impacts.

Share this post


Link to post
Share on other sites

ha, well, I tried out Das Attorney's code and the game chugged. For like 30 seconds. Then it printed out a point that was about 2 inches in front of me. And no, I wasn't pointing at the ground ;) I tried increasing the sleep interval to .1, but that didn't seem to help any.

---------- Post added at 09:06 ---------- Previous post was at 08:53 ----------

Ok, the following doesn't make the game chug, but the _last_pos never changes more than a couple inches from me. Tested by running around and comparing with shooting at those same locations from a single spot, and the bullet always seems to become !alive very close to me.

GunHandler = player addeventhandler ["Fired",
{
	private ["_bullet", "_last_pos"];
	_bullet = _this select 6;
	waitUntil {!alive _bullet}
	_last_pos = getPosATL _bullet;    
	player sideChat format ["Pos: %1, Time = %2", _last_pos, time]; 
} ];

Share this post


Link to post
Share on other sites

Perhaps isNull will be better than not alive? Anyway I think, that pos check must be inside waitUntil loop, trying to get position of bullet, that is gone (and we are waiting for that in waituntil) is futile, isn't...

For sure would be great to have a couple of additional event handlers. Ammo hit, explosion, even close passing by (suppresion), like in VBS2. Workarounds usually are CPU-heavy.

Following is mostly for curiosity, as most probably far heavier and not so reliable, still - it is some alternative and perhaps somehow useful.

Teoretically there should be a way to wait, until bullet is gone, then detect nearby shooter's aiming position (obtained in shooting moment) via nearObjects some objects of special classes/types created at hit event for some visuals/effects. For A2:

#crater - ground hits,

#crateronvehicle - vehicle/body/buildings (possible not all buildings/structures) hits.

(these two are long living, so must be obtained each already existing to sift off old ones (for this eg craters can be checked first time around aiming position in shooting moment, before bullet reach its destination), still it is not reliable, as there can be many new impacts there in one check cycle, if more than one bullet flies towards that point at the moment)

additionally: #explosion object type for "boom!s" - short live.

Something like:

RYD_WhenFired = 
{
private ["_unit","_bullet","_pos","_previous","_past","_new","_positions"];

_unit = _this select 0;
_bullet = _this select 6;

_pos = screenToWorld [0.5,0.5];
_previous = (_pos nearObjects ["#crater",15]) + (_pos nearObjects ["#crateronvehicle",15]);

[_bullet,_pos,_previous] spawn//because we can't use waitUntil in code called from within EH, we need to spawn separate scope in scheduled environment. This may cause unwanted delays though, also if we will spawn whole code instead of call. 
//Some crude alternative may be to use sqs with "~" as sleep (but we don't know, how long, must be somewhat calculated from distance and bullet speed (from config perhaps?)), 
//the only known to me reasonable way to make script wait outside scheduler, and rare situation, where sqs can do something, that sqf can't (?) 
	{
	_bullet = _this select 0;
	_pos = _this select 1;
	_previous = _this select 2;

	waitUntil {(isNull _bullet)};

	_past =(_pos nearObjects ["#crater",15]) + (_pos nearObjects ["#crateronvehicle",15]);//increase ranges, if no new crater is detected after hit. 
//May be needed for bigger shooting distancies, as used method of determining aiming point doesn't count ballistics, dispersion, zeroing and such, so real impact position can be quite far from screenToWorld aiming position. 

	_new = _past - _previous;

	_positions = [];

		{
		_positions set [(count _positions),getPosATL _x]
		}
	foreach _new;

	player sidechat format ["craters: %1 pos: %2",_new,_positions]
	}
};

GunHandler = player addeventhandler ["Fired",{nul = _this call RYD_WhenFired}];

Aiming position detection will work only for player though. For AI I'm not sure. Using aimpos then cast a ray from shooter's barrel through aimpos as far, as LOS become obstructed or something? Only guess, and looks heavy. Not sure, if this will work in A3, most probable its reliability is questionable anyway, and seems to be much heavier than simple following the bullet, so yeah, again - we need those EHs. Still core method alone can be used instead of not available "ammoHit" or "explosion" EH to detect "boom!s" and bullet hits around known object/position. Or passings, if quick nearobjects checks would be used with isKindOf "BulletCore" condition or something.

Possibly "#crateronvehicle" can be a key to determine, which exact part of body/vehicle was hit if converted to the model coordinates.

Edited by Rydygier

Share this post


Link to post
Share on other sites

ok, what was working last night is no longer working... did they do another update?

---------- Post added at 21:55 ---------- Previous post was at 20:37 ----------

Ok, got this working:

GunHandler = player addeventhandler ["Fired",  
{
_this spawn
{
	_bullet = _this select 6;
	_pos = getPosATL _bullet;
	while {alive _bullet} do {_pos = getPosATL _bullet;};
	_bomb = "R_80mm_HE" createVehicle _pos;
	_bomb setVectorUp [0, 9, 0.1];
};
}];

There's a problem with it though: whether I use isNull or alive as the condition in the while, if the bullet ricochets, it won't necessarily be counted as dead or gone. Is there any way to get the first time it hits something that isn't air?

Share this post


Link to post
Share on other sites

Ok, so I tried changing the {alive _bullet} condition to {damage _bullet == 0}, but it turns out that the damage is never equal to anything but zero (used some diagnostic messages to discern this). So how does the game know when the bullet has hit enough things to be counted as dead? Is it based on its velocity? Any ideas?

Share this post


Link to post
Share on other sites

I used the following code to calculate where a bullet landed. It worked for me in Arma 2. Maybe it will work for you. _bullet would be the bullet object from your event handler. Hopefully you need this for some special thing you are scripting. If you want to do this all the time for every bullet fired, you probably will have performance issues.

// ***************************************************************************************
// * We calculate a bullet collision point by trapping when bullet getpos no longer
// * returns a position.  Last good pos was the collision point.
// ***************************************************************************************
	_hitPos = [0,0,0];
	_done = false;
	while {(!_done )} do
	{
	   //sleep .005;
	   _pos = getpos _bullet;
	   if (_pos select 0 > 0) 
	   then 
	   {
			_hitPos = _pos;
	   }
		else
	   {
			_done = true;
	    };
	};   // end while

Share this post


Link to post
Share on other sites

That looks like another good way to do it, but if I'm reading it correctly, it still won't detect ricochets, only dead bullets when they get reset to 0,0,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  

×