Hypnomatic

Quick and fun projectile path tracing!

83 posts in this topic

This is a fairly simple script I began writing to after being a bit curious about how ARMA's bullet physics worked, particularly the ricocheting. Recently there was a post on /r/ARMA about bullet penetration, so I cleaned it a bit up to get what you see below. This'll basically trace the movements of projectiles, so you can very clearly see their flight path, arc, and interaction with cover. It's not perfect, but it does what it needs to pretty well. Plus it's surprisingly addicting to just run around and shoot stuff just to see what happens to the bullets.

UPDATE 10/26/2013:

As some of you may have seen, Dslyecxi recently made a video that featured a modified version of this script, where the color of the line was reflective of the velocity of the bullet at that moment. He posted his modifications, which are now implemented in the main script! To activate it, pass true as the seventh parameter, like so:

[player, nil, nil, nil, nil, nil, true] call hyp_fnc_traceFire;

Note that as it stands, enabling the velocity-based coloring will override whatever color you specify in the second parameter. I have an idea or two of ways to fix it, but wanted to get this update out there first.

Also, I completely forgot that the Steam Workshop was a thing, so I published a very simple mission with this script, and Tonic's Virtual Ammobox System and Virtual Vehicle Spawner enabled here:

http://steamcommunity.com/sharedfiles/filedetails/?id=189421090

If there are any problems with the Steam Workshop mission, please mention them to me, as I very rarely actually publish missions, just scripts.

The code:

Download the raw code: https://raw.github.com/hypnomatic/ARMA_Examples/master/Tracers%20Script/Tracer_v0-2-1.sqf

Link to Steam Workshop page for a simple mission featuring this script: http://steamcommunity.com/sharedfiles/filedetails/?id=189421090

How to use:

For basic use on just yourself, assuming you don't want to deal use the Steam Workshop mission, all you need to do is create a new mission, and paste the linked code into your init.sqf. After all that code in your init.sqf, add the line:

 [] call hyp_fnc_traceFire;

Save the file, restart your mission, and you should be good to go! With no extra parameters, this code is functionally equivalent to the original: it creates red lines behind projectiles fired by the player that are super smooth and persist forever. You can specify more parameters within the square brackets if you want a more specific outcome, as in the following examples.

 [] call hyp_fnc_traceFire;

Save the file, restart your mission, and you should be good to go! With no extra parameters, this code is functionally equivalent to the original: it creates red lines behind projectiles fired by the player that are super smooth and persist forever. You can specify more parameters within the square brackets if you want a more specific outcome, as in the following examples.

The syntax and expected parameters are as follows: (Note that all 7 parameters have default values, so you don't need to specify all of them if you don't want that specific feature.)

[_unit, _color, _lifetime, _interval, _maxDistance, _maxDuration, trackVel] call hyp_fnc_traceFire;

  • 0: _unit - Unit or vehicle to trace the projectiles of. Defaults to the player if no other parameter is specified.
  • 1: _color - Color array for all lines fired by this unit. This is an array formatted as [r,g,b,a], with each value being between 0 and 1. (BIS wiki page)
  • 2: _lifetime - Maximum number of seconds the projectile's line should linger after firing. Note that this timer starts at the same time as maxDuration, but is not checked until after the script finishes drawing a line. This can be thought of as a lower bound for how long a line will exist, as all lines will persist AT LEAST for lifetime's duration.
  • 3: _interval - Number of frames to skip between each adding segment of the line. Defaults to skipping no frames, so the lines are updated every frame.
  • 4: _maxDistance - Maximum distance from the initial position a projectile's line should be updated. Defaults to no maximum.
  • 5: _maxDuration - Maximum number of seconds from firing a projectile's line should be updated. Defaults to no maximum.
  • 6: _trackVel: If true, _color is overridden by the a color indicative of velocity at that moment. Thanks to Dslyecxi for this one! (Default false)

All of these options may be a bit confusing, so let me offer an example or two:

[player, [1,0,0,1], 3, 2, nil, 3] call hyp_fnc_traceFire; 

Can be thought of as saying:

Track every projectile of:

the player,

with a red line,

that will last for at least 3 seconds,

that is updated every third frame (ie 2 frames skipped between each update),

with no limit on distance,

but will not be updated for more than 2 seconds.

Now, if you want to completely omit a parameter so the default value is used, you have two options. You can either pass nil in place of that parameter, as in the example, which is ARMA's equivalent of "nothing". If you only want to pass specify a unit, and use the defaults for everything else, simply omitting all unwanted parameters like so:

[player] call hyp_fnc_traceFire;

However note that this only works if you want to leave out all parameters after the ones you specify. So if I wanted to specify a player and a max duration, I would need to pass:

[player, nil, nil, nil, nil, 5] call hyp_fnc_traceFire;

If you don't really mess with scripts much, this may be a bit tough to wrap your head around, so I'll be happy to answer any questions you may have.

To get a bit more fancy, you can create a few units/vehicles in the editor, name them, and follow the example near the top of this post to specify your own parameters! Just put whatever you named your unit in the editor in the first parameter, and you're good to go! Just as an example:

[player] call hyp_fnc_traceFire;
[heli1] call hyp_fnc_traceFire;
[car1] call hyp_fnc_traceFire;

Would cause bullets fired by the player's unit, heli1, and car1 to be traced with default options.

To give you yet another idea for what you can do, the following code will cause all units on the map to have their projectiles traced with team-specific colors that disappear after 3 seconds:

{
   if (faction _x == "OPF_F") then {
       [_x, [1,0,0,1], 3, 2, nil, 3] call hyp_fnc_traceFire; 
   };
   if (faction _x == "BLU_F") then {
       [_x, [0,0,1,1], 3, 2, nil, 3] call hyp_fnc_traceFire; 
   };
   if (faction _x in ["IND_F", "IND_G_F", "CIV_F"]) then {
       [_x, [0,1,0,1], 3, 2, nil, 3] call hyp_fnc_traceFire; 
   };
} forEach allUnits;

In Use:

Here's Dslyecxi's recent video featuring this script with his now-implemented modifications:



And here's a snazzy video by Jester814 that makes fairly heavy use of the original version of this script:



Notes/Known Bugs:

- Many optics, and some vehicle interiors (Pawnee comes to mind) do not play nicely with the drawn lines. A chunk of space floating in front of the sight will block out the lines behind them, so I recommend testing without optics. The Pawnee, for whetever reason, does not show any drawn lines at all in first person, so you need to enter third person to see lines from it.

- Water *mostly* works. Try it and you'll see what I mean. My guess is that it's getting the position relative to the sea level fine, but then has the height of the wave below it added, causing some mildly bendy lines.

- You may notice that the "fired" eventHandler has a seemingly redundant parameter added on. This actually is an interesting consequence of having the code spawned, as it seemed the scheduler put just enough of a delay between the event firing and the code within the spawn executing that the first gotten position of the bullet would be a few meters away. So this gets the first position before the spawn, and passes it in, and all seems to work well. Note that I don't actually have much scientific evidence to backup my theory, just that the first gotten position within the spawn was certainly late, while outside the spawn it was just fine.

Edited by Hypnomatic
Update 10/26/2013

Share this post


Link to post
Share on other sites

sounds real cool. giving it a try now. thanks!

edit - couldnt get it working. pity. sounds interesting.

Edited by twisted

Share this post


Link to post
Share on other sites

Nice, it works well for me. Interesting to see the performance cost of lots of simple 3D lines too!

Here's a quick fix to get the traces working over the ocean:

...
//Assemble the array of positions and push it to the global array
           waitUntil {
               if (isNull _bullet) exitWith {true};
               _positions set [count _positions, position _bullet];
               firedBullets set [_index, _positions];
           };
...

Edited by ceeeb
Revised code and removed link to feedback tracker, since the position format uses different datums over land and sea!!!

Share this post


Link to post
Share on other sites
sounds real cool. giving it a try now. thanks!

edit - couldnt get it working. pity. sounds interesting.

Just put all that code into init.sqf, loaded the mission and preview.

Share this post


Link to post
Share on other sites
sounds real cool. giving it a try now. thanks!

edit - couldnt get it working. pity. sounds interesting.

Yeah, as Kylania noted, just put the chunk of code in your init.sqf and preview the mission. Also note that you need to add at the very least something like:

[player] call hyp_fnc_traceFire; 

To make it draw lines for your player, as just the main chunk of code doesn't specify any units to watch. If you try that, it hopefully "should" work.

Nice, it works well for me. Interesting to see the performance cost of lots of simple 3D lines too!

Here's a quick fix to get the traces working over the ocean:

...

Yeah, how this hit performance was interesting to watch. Now, I'm not 100% sure about how the Draw3D eventHandler works, so I need to do a few tests to see how much of the performance hit was caused by the drawLine3D itself, and how much was caused simply by the sheer number or elements in the arrays to iterate through.

Also I'll plug in your change tomorrow. Don't have the chance to test it tonight unfortunately, though. Thanks!

Share this post


Link to post
Share on other sites

I've always been doing that with non-moving particles instead of lines. Might wanna give that a try...

Here's how my old script worked (adapted on the fly – untested in ArmA3):

// this addEventHandler ["fired", { [_this] spawn ArA_fnc_tracebullet; };

ArA_fnc_tracebullet = {
_unit = _this select 0;
_bullet = _this select 6;
_start = velocity _bullet;

_lifeTime = 2; //seconds
_limit = 1000 //meters

while {(!isNull _bullet) and (velocity _bullet > 0) and (player distance _bullet < _limit)} do {
	_vel = velocity _bullet;
	_r = 1 - _vel / _start;
	_g = _vel / _start;
	_b = 0;
	drop ["\Ca\Data\missileSmoke","","Billboard",0.1,_lifeTime,[0,0,0],[0,0,0],0,1.275,1,0,[0.1 + 0.0005*(player distance _shot),0.1],[[(player distance _shot) / _limit,1-(player distance _shot) / _limit,0,(player distance _shot) / 25],[_r,_g,_b,1]],[1,0],0,0,"","",_shot];
	sleep 0.01;
};
};

I've limited it to trace bullets for only 1000 meters.

Particle lifetime and size can still be adjusted. Right now, they particles get bigger, the further they are away. So this was originally meant to be viewed from the shooter-point of view, not for walking around the bulletpaths. Using a longer particle-lifetime will make that possible.

Edited by Tajin
1 person likes this

Share this post


Link to post
Share on other sites

Very cool! Plus it proofs that you probably shouldn't hide behind a portable toiled in a firefight. :D

Share this post


Link to post
Share on other sites

Sweet Script - Thank you. Now, if I only had a wind direction / speed indicator, sniping practice would be set.

Share this post


Link to post
Share on other sites

Can't get it to work, using the dev build.

I put it to init.sqf + added [player] call hyp_fnc_traceFire;

I have "clear lines" in the action menu, but nothing happens when I fire the weapon. Problems with the dev build, or with my graphics settings?

Edit: Nevermind... After restarting Arma, everything is working...

Edited by Gekkibi

Share this post


Link to post
Share on other sites

I got it to work by realizing all the code goes in the init.sqf. it's great.

Share this post


Link to post
Share on other sites

Is it possible it will works for A2 OA too?

ItÅ› great for testing and tuning custom mod:-)

Share this post


Link to post
Share on other sites

Sorry but do you mean make a document and put it in the mission file folder and name it init.sqf? and then the second string of code goes in the players init? or maybe in the local exe in the debug? I have tried some things but can't get it right.

I'm sorry but i'm trying really hard to learn this stuff. I have read lots of things but when I read about these sqf files it it is explaining on how to make briefings. Sorry for looking lazy and asking questions on forums but I am banging my head against the wall with this. :(

As I have mentioned before on this forum, I am really keen to learn this stuff and am not afraid to read things unlike most the people these days who demand video tutorials to learn how to do do anything.

Sorry if I sound like a complete noob but I guess when it comes to scripting, I guess that's what I am. Sorry if I offend anyone :(

Edited by thelog

Share this post


Link to post
Share on other sites

This is not a tracer mod, it's a script to trace the bullet path. think draw a line from the muzzle of your gun all the way until the bullet stops

Share this post


Link to post
Share on other sites
to make this clear.. is this like starwars phazer pewpew tracers or something?

No LOL, as Mr centipede said it's for tracing the bullet path. So the lines will stay on screen.

Share this post


Link to post
Share on other sites
This is not a tracer mod, it's a script to trace the bullet path.think draw a line from the muzzle of your gun all the way until the bullet stops

that's an exact definition of what a tracer IS and what confused me and reason I asked to clarify what it does..

thelog what was funny?

Share this post


Link to post
Share on other sites

Ok so I have made the innit.sqf file crammed it with the first box of code and given my soldier the second line of code. I have named him garry. so it looks like this

[_garry] call hyp_fnc_traceFire; 

I have tried putting it at the bottom of the first lot of code but no joy, and I have also placed it above the last to lines. anyone got any ideas for me?

All the best

Good Vibes

---------- Post added at 07:47 ---------- Previous post was at 07:41 ----------

thelog what was funny?

When you said "phazer pew pew starwars" it made me laugh out loud. Sorry if you thought I was laughing at you taking the piss or something. I'm not that kind of person.

---------- Post added at 08:17 ---------- Previous post was at 07:47 ----------

Edited by thelog

Share this post


Link to post
Share on other sites

thelog, I didn't take it personal I just didn't get what was funny.

Mr_Centipede I think what I am trying to understand here is what its intended purpose /use is

so let me rephrase the question, would this be useful way to troubleshoot a person trying to figure out projectile zeroing?

Share this post


Link to post
Share on other sites

The purpose is to know will a bullet penetrate a certain object, and what that object do to the bullet path after is been penetrate it. Zeroing could work also. Basically just a fun way to know where the bullet goes after it exited the barrel

Share this post


Link to post
Share on other sites

I can see this as a very handy developer tool Hypnomatic thank you for making it.

thanks thelog for Adding video & thanks Mr_Centipede for explinations.

@ Hypnomatic you may want to add the vid to the first post for a better preview description

+1

Edited by MadM0nkey
proper credits & Thankyou

Share this post


Link to post
Share on other sites

So can anyone just clarify where exactly I put this line of code

[_name] call hyp_fnc_traceFire;  

I understand it goes under the rest of it but I can't seem to get it to work. I have made the unit Player1 so i'm guessing it looks like this

[_player1] call hyp_fnc_traceFire;  

Share this post


Link to post
Share on other sites
Is it possible it will works for A2 OA too?

ItÅ› great for testing and tuning custom mod:-)

Sort of, IIRC the drawLine3D command is new to ARMA3, so I would need to come up with some particle or something to use. Everything else in the script should work in ARMA 2 though, so I'll toy with a few different particles to see if anything looks good. Maybe something like Tajin's example.

thelog, I didn't take it personal I just didn't get what was funny.

Mr_Centipede I think what I am trying to understand here is what its intended purpose /use is

so let me rephrase the question, would this be useful way to troubleshoot a person trying to figure out projectile zeroing?

As mentioned above, this isn't really a script for gameplay purposes, but more so a script for just testing bullet mechanics and screwing around in general.

Sorry but do you mean make a document and put it in the mission file folder and name it init.sqf? and then the second string of code goes in the players init? or maybe in the local exe in the debug? I have tried some things but can't get it right.

I'm sorry but i'm trying really hard to learn this stuff. I have read lots of things but when I read about these sqf files it it is explaining on how to make briefings. Sorry for looking lazy and asking questions on forums but I am banging my head against the wall with this. :(

As I have mentioned before on this forum, I am really keen to learn this stuff and am not afraid to read things unlike most the people these days who demand video tutorials to learn how to do do anything.

Sorry if I sound like a complete noob but I guess when it comes to scripting, I guess that's what I am. Sorry if I offend anyone :(

To give you an example, let's say I create 2 soldiers, and a tank in the editor, and name the soldiers soldier1 and soldier2, and the tank tank1. If you haven't already saved the mission, do so now, then navigate to it's folder (Mine would be My Documents\Arma 3 - Other Profiles\Hypnomatic\missions\WhateverINamedTheMission.Altis) outside of ARMA and create the file init.sqf (Make sure you have file extension visible so you don't just create init.sqf.txt!). Into init.sqf I would paste:

/*
General init for the tracer function
*/
firedBullets = [];

addMissionEventHandler ["Draw3D", { //On every frame...
   {
       for "_i" from 0 to (count _x) - 2 do {
           drawLine3D [_x select _i, _x select (_i + 1), [1,0,0,1]]; //...draw lines connecting the positions on the path that the bullet took...
       };
   } forEach firedBullets; //...for every bullet that has been fired since the last clearing.
}];
player addAction["Clear Lines", {firedBullets=[];}]; //Clears the lines of all bullets no longer in the air

/*
Syntax: 
   [_unit] call hyp_fnc_traceFire;
Params: 
   _unit: Either a vehicle or unit
Return Value:
   Scalar: The ID of the "fired" EventHandler that was added.
*/
hyp_fnc_traceFire = {
   (_this select 0) addEventHandler ["fired", {
       [_this, (position(_this select 6))] spawn {
           private["_params","_initialPos","_bullet","_index","_positions"];
           //Vars and Params
           _params     = _this select 0;
           _initialPos = _this select 1;
           _bullet     = _params select 6;
           _index      = count firedBullets;
           _positions  = [_initialPos];

           //Assemble the array of positions and push it to the global array
           waitUntil {
               if (isNull _bullet) exitWith {true};
               _positions set [count _positions, position _bullet];
               firedBullets set [_index, _positions];
           };
       };
   }]
};  

[soldier1] call hyp_fnc_traceFire;
[soldier2] call hyp_fnc_traceFire;
[tank1] call hyp_fnc_traceFire;

(Note the addition of the 3 lines at the bottom)

Save it and launch the mission, and you should be good!

Also dropping a message to Jester about using his video in the post. If he's all good with it I'll add it to the OP.

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