Jump to content
LSValmont

Changing all regular ammo to Tracer ammunition

Recommended Posts

Dear follow Arma addicts, can anyone point me towards a performance conscious script for:

 

1) Replacing all the non tracer ammunition from both player and ai with tracer ammunition, both at their weapons and inventories.

2) I believe tracer ammunition effects only happens when the magazine is almost empty. Is there any way to make every round have (or simulate) tracer effects?

 

 Basically I want to simulate old school battlefield games (BF2, BF3) were all rounds have tracer like effects that help players identify the origin and location that fire is coming from. (I need to up the feedback and gameplay friendliness of my mission while compromising some realism).

 

Thank you in advanced!

Share this post


Link to post
Share on other sites

This is by no means an easy task, especially considering that magazine classes not always have a tracer version, nor are the classnames consistent enough to make a reliable script without thorough error checking (gets into nightmare territory if you want to include compatibility to other mods).

You can check for tracer mags like this:

_allMagazines = "getNumber (_x >> 'scope') >=  2" configClasses (configFile >> "CfgMagazines") apply {configName _x};
_allTracers  = "getNumber (_x >> 'tracersEvery') > 0" configClasses (configFile >> "CfgMagazines") apply {configName _x};

Magazines that act like tracers have the tracerEvery value above 0.

Sometimes tracer magazine classnames include the name of the color, sometimes it's simply named with a "tracer" suffix.

A solution would be  to compare magazines by iterating through the (at most 3 deep from what I can tell) getUnitLoadout nested array, and replace it with a similar named mag from the tracer array, like this:

//while iterating over getUnitLoadout array
_allValidTracers = _allTracers select {toUpper _x find toUpper _mag >= 0};
if (count _allValidTracers > 0) then {/*replace element*/};//might pick a random one or the first element, should be a tracer in any case

It's probably faster and more fool proof to make 4-5 custom unit loadouts using tracers to achieve what you want.

 

Cheers

  • Like 4

Share this post


Link to post
Share on other sites

If you are not in a hurry, I'll give you (end of March) a little script adding light on each bullets. I'm not at home and far from Arma. On the other hand, I remember some FPS drops in intense battle. But the effects are fun by night, bullets enlightening the landscape.

  • Like 4

Share this post


Link to post
Share on other sites
2 hours ago, pierremgi said:

If you are not in a hurry, I'll give you (end of March) a little script adding light on each bullets. I'm not at home and far from Arma. On the other hand, I remember some FPS drops in intense battle. But the effects are fun by night, bullets enlightening the landscape.

Thank you @pierremgi I am not in a hurry since I am waiting for OLD MAN (The mission, not @Grumpy Old Man) to be integrated into Arma 3 (it is already integrated in the Dev Versions).

 

3 hours ago, Grumpy Old Man said:

This is by no means an easy task, especially considering that magazine classes not always have a tracer version, nor are the classnames consistent enough to make a reliable script without thorough error checking (gets into nightmare territory if you want to include compatibility to other mods).

You can check for tracer mags like this:


_allMagazines = "getNumber (_x >> 'scope') >=  2" configClasses (configFile >> "CfgMagazines") apply {configName _x};
_allTracers  = "getNumber (_x >> 'tracersEvery') > 0" configClasses (configFile >> "CfgMagazines") apply {configName _x};

Magazines that act like tracers have the tracerEvery value above 0.

Sometimes tracer magazine classnames include the name of the color, sometimes it's simply named with a "tracer" suffix.

A solution would be  to compare magazines by iterating through the (at most 3 deep from what I can tell) getUnitLoadout nested array, and replace it with a similar named mag from the tracer array, like this:


//while iterating over getUnitLoadout array
_allValidTracers = _allTracers select {toUpper _x find toUpper _mag >= 0};
if (count _allValidTracers > 0) then {/*replace element*/};//might pick a random one or the first element, should be a tracer in any case

It's probably faster and more fool proof to make 4-5 custom unit loadouts using tracers to achieve what you want.

 

Cheers

 

Thank you @Grumpy Old Man, I agree about making custom loadouts being the best option other than @pierremgi 's. I will be using that until  @pierremgi can share his script 😉

Share this post


Link to post
Share on other sites

Well, still stuck 17,000 km far from my home...

I decided to shift on another PC. As I have plenty of time these ugly days, here is a brand new script:

 

Spoiler



0 = [] spawn {
  MGI_LIMITTRACERS = TRUE;
  MGI_FORCESOMETRACERS = 4;

  While {TRUE} do {
    _allUnits = allUnits select {isNil {_x getVariable "MGI_Tracers"}};
    {
      _unit = _x;
      _sideColor = if (side _unit == WEST) then [{[235, 170, 170]},{if (side _unit == EAST) then [{[170,255,170]},{[255,255,170]}]}];
      _sideColorAmbient = if (side _unit == WEST) then [{[2.35, 1.7, 1.7]},{if (side _unit == EAST) then [{[1.7,2.55,1.7]},{[2.55,2.55,1.7]}]}];
      _unit setVariable ["MGI_Tracers",[_sideColor,_sideColorAmbient]];
      
      _unit addEventHandler ["firedMan",{
        params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"];
        if (_weapon != "Throw" && _weapon != handgunWeapon _unit) then {
          private _tracerEnabled = FALSE;
          if (MGI_LIMITTRACERS) then {
            call {
              if (_unit ammo _muzzle < ((getNumber (configFile >> "cfgMagazines" >> _magazine >> "lastRoundsTracer")) max 5)) exitWith {
                _tracerEnabled = TRUE;
              };
              _tracersEvery = getNumber (configFile >> "cfgMagazines" >> _magazine >> "tracersEvery");
              if (_tracersEvery == 0 and MGI_FORCESOMETRACERS >0) then {_tracersEvery = MGI_FORCESOMETRACERS};
              if (_tracersEvery >0 && {((_unit ammo _muzzle)+1) mod _tracersEvery == 0}) then {
                _tracerEnabled = TRUE;
              };
            };
          } else {
            _tracerEnabled = TRUE
          };
          private ["_sideColor","_sideColorAmbient"];
          if (_tracerEnabled) then {
            if (getText (configfile >> "CfgMagazines" >> _magazine >> "nameSound") != "missiles") then {
              _sideColor = (_unit getVariable "MGI_Tracers") #0;
              _sideColorAmbient = (_unit getVariable "MGI_Tracers") #1;
            } else {
              _sideColor = [255,255,255];
              _sideColorAmbient = [2.55,2.55,2.55];
            };

            _light = "#lightPoint" createVehicleLocal (getPosVisual _projectile);
            _light lightAttachObject [_projectile,[0,-0.5,0]];
            _light setLightColor _sideColor;
            _light setLightAmbient _sideColorAmbient;
            _light setLightIntensity (if (sunOrMoon > 0.5) then [{30000},{100}]);
            _light setLightDayLight true;
            _light setLightUseFlare true;
            _light setLightFlareSize .4;
            _light setLightFlareMaxDistance 2000;
            
            [_light,_projectile] spawn {
              params ["_light","_projectile"];
              waitUntil {uiSleep 0.1; isNull _projectile};
              LightDetachObject _light;
              deleteVehicle _light;
            };
          };
        };
      }]
    } forEach _allUnits;
    uisleep 3;
  }
};


 

 

The best way is to run it, independently on each played PC, say like inside  initPlayerLocal.sqf  (I can't imagine any sync/broadcast for all that stuff! Avoid any remote execution)

 

There are 2 parameters:

MGI_LIMITTRACERS (boolean) :   If you set it to FALSE, all bullets/shells/missiles will have an attached light. That could be enchanting but not very realistic... and resource consuming.

If you let it to TRUE, you will force all end of magazines for custom tracers (set to 5 here);

 

MGI_FORCESOMETRACERS (number):   if set to zero, no extra thing. If you set it >O, 2 cases:

  - the current magazine is already able to fire a tracer regularly (say every 5 bullets): The vanilla parameter is taken into account and the script adds a light on these tracers only;

  - there is no tracer supposed to be fired regularly : in this case, your parameter will add tracers every interval you set.

 

Colors used are:

white for any missile,

red for BLUFOR, green for OPFOR, yellow for INDEP.

Note: I didn't cope with current tracer colors. So, in some cases, my tracer colors  are different from BI tracer ones: For example,  the INDEP NYX (I_LT_01_AA_F), is vanilla fitted with red tracers for HMG12.7. (should be yellow... I don't know why this exception).

 

I'll probably add this code in a MGI module... once at home.

Enjoy!

 

  • Like 2
  • Thanks 4

Share this post


Link to post
Share on other sites
On 4/5/2020 at 9:48 AM, pierremgi said:

Well, still stuck 17,000 km far from my home...

I decided to shift on another PC. As I have plenty of time these ugly days, here is a brand new script:

 

  Reveal hidden contents

 



0 = [] spawn {
  MGI_LIMITTRACERS = TRUE;
  MGI_FORCESOMETRACERS = 4;

  While {TRUE} do {
    _allUnits = allUnits select {isNil {_x getVariable "MGI_Tracers"}};
    {
      _unit = _x;
      _sideColor = if (side _unit == WEST) then [{[235, 170, 170]},{if (side _unit == EAST) then [{[170,255,170]},{[255,255,170]}]}];
      _sideColorAmbient = if (side _unit == WEST) then [{[2.35, 1.7, 1.7]},{if (side _unit == EAST) then [{[1.7,2.55,1.7]},{[2.55,2.55,1.7]}]}];
      _unit setVariable ["MGI_Tracers",[_sideColor,_sideColorAmbient]];
      
      _unit addEventHandler ["firedMan",{
        params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle"];
        if (_weapon != "Throw" && _weapon != handgunWeapon _unit) then {
          private _tracerEnabled = FALSE;
          if (MGI_LIMITTRACERS) then {
            call {
              if (_unit ammo _muzzle < ((getNumber (configFile >> "cfgMagazines" >> _magazine >> "lastRoundsTracer")) max 5)) exitWith {
                _tracerEnabled = TRUE;
              };
              _tracersEvery = getNumber (configFile >> "cfgMagazines" >> _magazine >> "tracersEvery");
              if (_tracersEvery == 0 and MGI_FORCESOMETRACERS >0) then {_tracersEvery = MGI_FORCESOMETRACERS};
              if (_tracersEvery >0 && {((_unit ammo _muzzle)+1) mod _tracersEvery == 0}) then {
                _tracerEnabled = TRUE;
              };
            };
          } else {
            _tracerEnabled = TRUE
          };
          private ["_sideColor","_sideColorAmbient"];
          if (_tracerEnabled) then {
            if (getText (configfile >> "CfgMagazines" >> _magazine >> "nameSound") != "missiles") then {
              _sideColor = (_unit getVariable "MGI_Tracers") #0;
              _sideColorAmbient = (_unit getVariable "MGI_Tracers") #1;
            } else {
              _sideColor = [255,255,255];
              _sideColorAmbient = [2.55,2.55,2.55];
            };

            _light = "#lightPoint" createVehicleLocal (getPosVisual _projectile);
            _light lightAttachObject [_projectile,[0,-0.5,0]];
            _light setLightColor _sideColor;
            _light setLightAmbient _sideColorAmbient;
            _light setLightIntensity (if (sunOrMoon > 0.5) then [{30000},{100}]);
            _light setLightDayLight true;
            _light setLightUseFlare true;
            _light setLightFlareSize .4;
            _light setLightFlareMaxDistance 2000;
            
            [_light,_projectile] spawn {
              params ["_light","_projectile"];
              waitUntil {uiSleep 0.1; isNull _projectile};
              LightDetachObject _light;
              deleteVehicle _light;
            };
          };
        };
      }]
    } forEach _allUnits;
    uisleep 3;
  }
};

 

 

 

 

 

The best way is to run it, independently on each played PC, say like inside  initPlayerLocal.sqf  (I can't imagine any sync/broadcast for all that stuff! Avoid any remote execution)

 

There are 2 parameters:

MGI_LIMITTRACERS (boolean) :   If you set it to FALSE, all bullets/shells/missiles will have an attached light. That could be enchanting but not very realistic... and resource consuming.

If you let it to TRUE, you will force all end of magazines for custom tracers (set to 5 here);

 

MGI_FORCESOMETRACERS (number):   if set to zero, no extra thing. If you set it >O, 2 cases:

  - the current magazine is already able to fire a tracer regularly (say every 5 bullets): The vanilla parameter is taken into account and the script adds a light on these tracers only;

  - there is no tracer supposed to be fired regularly : in this case, your parameter will add tracers every interval you set.

 

Colors used are:

white for any missile,

red for BLUFOR, green for OPFOR, yellow for INDEP.

Note: I didn't cope with current tracer colors. So, in some cases, my tracer colors  are different from BI tracer ones: For example,  the INDEP NYX (I_LT_01_AA_F), is vanilla fitted with red tracers for HMG12.7. (should be yellow... I don't know why this exception).

 

I'll probably add this code in a MGI module... once at home.

Enjoy!

 

 

Hey, for some reason I wasn't aware of this reply! 

 

Thank you very much @pierremgi

 

Will test this ASAP!

Share this post


Link to post
Share on other sites

@pierremgi @Grumpy Old Man

 

This fnc does the job!

No performance impact, nothing attached, no network load, looks amazing and it is just perfect.


Thank you both for your input and help!

Spoiler



vReplaceAiMagsWithTracers = {
	params [
		["_unit", objNull, [objNull]]
	];
	if (isAgent TeamMember _unit) exitWith {/*it's an agent*/};
	private _weapons = [];
	_weapons = weapons _unit;
	if (count _weapons < 1) exitWith {};

	{
		private _compMags = [];
		_compMags = getArray (configfile >> "CfgWeapons" >> _x >> "magazines");
		// Determine right tracer color
		private _tracerColor = "red";
		switch (side _unit) do {
			case east: 			{_tracerColor = "green"};
			case independent: 	{_tracerColor = "yellow"};
		};
		_tracerColor = "yellow"; //Forced yellow color by Valmont
		// Find correct tracer mag name
		private _correctMag = _compMags select {toLower _x find "tracer" > 0};
		if (count _correctMag isEqualTo 0) exitWith {/*No tracer mags for this weapon*/};
		_correctMag = _compMags select {toLower _x find _tracerColor > 0};
		if (count _correctMag > 0) then {
			_correctMag = _correctMag select 0;
		} else {
			_correctMag = _compMags select {toLower _x find "tracer" > 0};
			_correctMag = _correctMag select {toLower _x find "red" < 0 && toLower _x find "green" < 0 && toLower _x find "yellow" < 0};
			_correctMag = _correctMag select 0;
		};

		// Add magazines and remove non tracer ones
		private _currentMags = (magazines _unit) select {_x in _compMags};
		private _nonTracerMags = _currentMags select {toLower _x find "tracer" < 0};
		private _amount = count _nonTracerMags;
		private _tracerMags = _currentMags select {toLower _x find "tracer" > 0};

		{_unit removeMagazines _x} forEach _nonTracerMags;
		_unit addMagazines [_correctMag, _amount];

		switch (_x) do
		{
			case primaryWeapon _unit:
			{
				_unit removePrimaryWeaponItem ((primaryWeaponMagazine _unit) select 0);
				_unit addPrimaryWeaponItem _correctMag;
			};
			case secondaryWeapon _unit:
			{
				_unit removeSecondaryWeaponItem ((secondaryWeaponMagazine _unit) select 0);
				_unit addSecondaryWeaponItem _correctMag;
			};
			case handgunWeapon _unit:
			{
				_unit removeSecondaryWeaponItem ((handgunMagazine _unit) select 0);
				_unit addHandgunItem _correctMag;
			};
			default
			{
				/* maybe lasermarker? */
			};
		};

	} forEach _weapons;
};


 

 

  • Like 2

Share this post


Link to post
Share on other sites

Hi @LSValmont,

 

this script looks very interesting. The less network traffic for Dedicated Server makes me looking for very interested.

To which way you integrated your fnc? Do you use a call via init.sqf or initserver.sqf?

 

Thanks a lot for sharing this idea.

  • Like 1

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

×