Jump to content
Sign in to follow this  
camo1018

Magic Bullet Script

Recommended Posts

Hi all,

I've been working on a script for scripted AI snipers.

I'm trying to create an illusion as if the AI sniper was very accurate by adding a "Fired" eventhandler that will (if it worked out) redirect the last fired bullet to the player.

This is what I have to so far...

_target = _this select 1;
_fired = _this select 0;
_bullet = nearestobject [_fired select 0,_fired select 4]; 

_Pa_shot = getpos _bullet;
_Pb_shot = getpos _target;
_abx_shot = (_Pb_shot select 0) - (_Pa_shot select 0);
_aby_shot = (_Pb_shot select 1) - (_Pa_shot select 1);
_abz_shot = (_Pb_shot select 2) - (_Pa_shot select 2);

_Pab_shot = [_abx_shot, _aby_shot, _abz_shot];

_bullet setVelocity _Pab_shot;
player sideChat "SHOT!";

Can anyone point me in the right direction?

Thanks in advance.

Share this post


Link to post
Share on other sites

Why so complicated?

Why don`t you simply use:

sniper doTarget player;
sniper addEventHandler ["FIRED", {player setDamage 1;}];
sniper fire "KSVK";

:rolleyes:

Share this post


Link to post
Share on other sites

If the sniper is far away, I'd suggest to implement a delay between the shot and the death of the player.

sniper addEventHandler ["FIRED", {[] exec "snipershot.sqf"}];

snipershot.sqf:

~1.0
player setdamage 1;

You could even have a very accurate delay between the shot and the death.

_dist = sniper distance player;
_bulletspeed = ???; (in metres per second)
_delay = _dist/_bulletspeed;
~_delay
player setdamage 1;

Mkay, the delay might rise the problem that the player notices that he was not hit before he dies (seeing bullet impact beside him or hear it whistling when it passes him very closely).

Edited by RogueTrooper

Share this post


Link to post
Share on other sites
If the sniper is far away, I'd suggest to implement a delay between the shot and the death of the player.

sniper addEventHandler ["FIRED", {[] exec "snipershot.sqf"}];

snipershot.sqf:

~1.0
player setdamage 1;

You could even have a very accurate delay between the shot and the death.

_dist = sniper distance player;
_bulletspeed = ???; (in metres per second)
_delay = _dist/_bulletspeed;
~_delay
player setdamage 1;

Some improvement :)

sniper addEventHandler ["FIRED", {[(_this select 4),(_this select 6)] exec "snipershot.sqf"}];

snipershot.sqf

_ammotype = _this select 0;
_bullet = _this select 1;

deleteVehicle _bullet;

_dist = sniper distance player;
_bulletspeed = getNumber(configFile >> "CfgAmmo" >> _ammotype >> "typicalspeed");
_delay = _dist/_bulletspeed;
sleep _delay;
player setdamage 1;

Share this post


Link to post
Share on other sites

Thanks for your inputs.

However, I am not looking to kill off the player as soon as the sniper fires. I want to create a sense of urgency for the player to take cover. If he fails to do so, I want the bullet to kill the player.

Share this post


Link to post
Share on other sites

Bump up the snipers skill with each shot instead of fancy speed calculations?

Share this post


Link to post
Share on other sites

I guess that would be the way to do this if I must.

I find that the current AI isn't menacing enough to have the player scrambling for cover.

Can an expert tell me if manipulating the fired bullet is even possible?

Share this post


Link to post
Share on other sites

add a fired eventhandler to the sniper, script running off that will have the bullet fired as _this select 6;

while bullet is alive, manipulate the bullet with some form of this below:

seVelocity and combine it with somekind of setVectorUpAndDir

Share this post


Link to post
Share on other sites

Were you able to get this to work?

I tried combinations of setVectorDir , setVectorUp and setVelocity but I was unable to get any wanted results out of it.

Share this post


Link to post
Share on other sites

It's possible to manipulate the bullet, but calculating exactly where it will end up relative to a moving player involves a fair amount of complex math, which includes some calculus.

Share this post


Link to post
Share on other sites

Or just create a bullet near the player along with a sound effect?

Share this post


Link to post
Share on other sites

The physics of this is a little more complicated than simply getting the heading from the firing position to the player. That method might work at very short distances, but at longer ranges (typical sniper ranges) you need to compensate for gravity and the velocity of the target.

Due to air resistance, bullets in ArmA 2 lose velocity over time; further complicating the calculations. However this might not have a significant impact for direct-fire targets. If you assume constant velocity, it's not too difficult to calculate the firing solution.

Let's assume we already have the following variables:

_bullet = the bullet object

_target = the player

First you should calculate the estimated time of travel for the bullet using the distance to the target (Note: I'm using functions from BI's functions module):

_velocity = velocity _bullet;
_bPos = getPosASL _bullet;
_tPos = getPosASL _target;
_tPos = [_tPos select 0,_tPos select 1,(_tPos select 2) + 1]; // add offset to target pos, otherwise the target position will be at the target's feet
_speed = _velocity call BIS_fnc_magnitude;
_dist = _bPos distance _tPos;
_et = _dist / _speed;

Then you can get the target lead:

_tVel = velocity _target;
_tPosAdj = [_tVel,_et] call BIS_fnc_vectorMultiply;
_tPosLead = [_tPos,_tPosAdj] call BIS_fnc_vectorAdd;

Now to compensate for graivty, we need to pick a position above the target to aim at:

_drop = 0 - (4.9 * (_et ^ 2)); // based on the equation X = Vo + 1/2 a t^2
_tPosFinal = [_tPosLead select 0,_tPosLead select 1,(_tPosLead select 2) - _drop];

Finally we get the resulting heading & velocity and apply it to the projectile:

_finalHeading = [_bPos,_tPosFinal] call BIS_fnc_vectorFromXToY;
_finalVelocity = [_finalHeading,_speed] call BIS_fnc_vectorMultiply;

_bullet setVectorDir _finalHeading;
_bullet setVelocity _finalVelocity;

Hopefully (if my math is correct) this will produce very accurate shots. If the air resistance causes problems you can try one of two things: apply a coefficient to the _et variable depending on the range (would require some trial & error) or apply a script to the bullet that negates the effect of air resistance.

Edit: Btw, make sure you call this script and not execVM it. You want it to run to completion before the bullet moves.

Hope this helps.

Edited by Big Dawg KS

Share this post


Link to post
Share on other sites

Why not just kill the player and play a firing sound a second afterwards?

Share this post


Link to post
Share on other sites
Why not just kill the player and play a firing sound a second afterwards?

Cause physics is fun. :p

Also, I personally hate cheap tricks like that. If you're going to fake it, fake it with precision.

Edited by Big Dawg KS

Share this post


Link to post
Share on other sites

The effect of air resistance on bullets is really quite massive, particularly right after the shot is fired. Assuming that the velocity will stay constant throughout the shot will produce wildly inaccurate firing solutions. A simple coefficient won't be of much help, either, because air resistance is a function of velocity (faster bullet = more resistance), and velocity is constantly changing as a result of air resistance.

Drop compensation isn't as simple as it would first appear, either. Whenever you compensate for drop, you must then again compensate for the fact that the initial upward component of the bullet's velocity vector has changed (you are aiming slightly higher to compensate for drop), which changes its drop profile. If the shot isn't taken from too far away, you can get away with a simple gravity calculation, but this method will not be accurate at sniper ranges.

I've looked into this problem extensively in the past. To get accurate results, you will need calculus, which I don't feel like going into here. Honestly, just letting an AI unit with high skill shoot will probably lead to more interesting, albeit less predictable, results.

Share this post


Link to post
Share on other sites

Ok I tested it now and found a problem with my original script. The initial velocity for the drop calculation should be zero. With that fixed it works pretty well at medium ranges. The deceleration of the round does throw it off at longer ranges though. I'm sure with tuning you could compensate for it.

---------- Post added at 01:18 PM ---------- Previous post was at 01:15 PM ----------

The effect of air resistance on bullets is really quite massive, particularly right after the shot is fired. Assuming that the velocity will stay constant throughout the shot will produce wildly inaccurate firing solutions. A simple coefficient won't be of much help, either, because air resistance is a function of velocity (faster bullet = more resistance), and velocity is constantly changing as a result of air resistance.

Yes this is true, but all you need for the above calculation is an accurate travel time. If you measure & plot the time for different ranges you could get pretty accurate results without doing heavy math. It won't be linear though like you said.

---------- Post added at 01:47 PM ---------- Previous post was at 01:18 PM ----------

Another update. Here's a helper script that gives the bullet a simplified ballistic trajectory without any air resistance/drag.

nodrag.sqf

_bullet = _this select 0;
_initVel = _this select 1;
_vZ = _initVel select 2;
_lt = time;

waitUntil{
_t = time - _lt;
_vZ = _vZ - (9.8 * _t);
_bullet setVelocity [_initVel select 0,_initVel select 1,_vZ];
_lt = time;
(!alive _bullet)
};

magicshot.sqf

_params = _this select 0;
_target = _this select 1;

_bullet = _params select 6;

_velocity = velocity _bullet; 
_bPos = getPosASL _bullet; 
_tPos = getPosASL _target; 
_tPos = [_tPos select 0,_tPos select 1,(_tPos select 2) + 1]; // add offset to target pos, otherwise the target position will be at the target's feet 
_speed = _velocity call BIS_fnc_magnitude; 
_dist = _bPos distance _tPos;
_et = _dist / _speed;  

_tVel = velocity _target; 
_tPosAdj = [_tVel,_et] call BIS_fnc_vectorMultiply; 
_tPosLead = [_tPos,_tPosAdj] call BIS_fnc_vectorAdd;

_vZ = 0;
_drop = _vZ - (4.9 * (_et ^ 2)); // based on the equation X = Vo + 1/2 a t^2 
_tPosFinal = [_tPosLead select 0,_tPosLead select 1,(_tPosLead select 2) - _drop];  

_finalHeading = [_bPos,_tPosFinal] call BIS_fnc_vectorFromXToY; 
_finalVelocity = [_finalHeading,_speed] call BIS_fnc_vectorMultiply; 

_bullet setVectorDir _finalHeading;
_bullet setVelocity _finalVelocity;

[_bullet,_finalVelocity] execVM "nodrag.sqf";

EH:

this addEventHandler ["fired",{[_this,player] call compile preprocessFileLineNumbers "magicshot.sqf"}]

Works very well.

Share this post


Link to post
Share on other sites

I believe that is exactly what I was looking for.

Thank you all for your inputs and help. I'll give Big Dawg's script a try later tonight. It's nice to know that this community has plenty of talented and helpful developers.

I've been trying to figure this out for hours early this morning but was about to give up to my frustration. With this, I hope things will be sorted out. It really wouldn't so much trouble if BI added functions for I think setWeaponDirection to actually force the AI to aim in a certain direction. Hopefully Arma 3 will have those, but this will do for now.

Once again, thanks for all your help.

Share this post


Link to post
Share on other sites

Big Dawg should code a Knife Missile from Dune type round.

Share this post


Link to post
Share on other sites

Very interesting, twirly. I wish I had stumbled on that when I was searching frantically for answers this morning. Thanks so much for that link and for your work.

EDIT: Everything worked out the way I wanted. Thank you all for your help! They have been very helpful.

EDIT 2: Now I'm wondering another possibility. Is it possible to find the point at which the bullet impacted? If that's not possible, is there any way to check whenever a bullet is close enough the player to count as being hit? I'm using this for a possible Line of Sight checker.

Edited by camo1018
Update

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  

×