Jump to content
nikiller

Need help for suppressors durability script

Recommended Posts

hi,

I would like to make a script to implement suppressors durability.

i.e: If you fire 30 shots with your suppressor it is removed from you inventory.

I found a script to detect if the player has suppressor but I don't know how to count the shots fired before the suppressor is removed. My guess is an addEventHandler fired but my knowledge are too small to make a script like that.

detect_suppressor.sqf by Das Attorney

         _arr = 
       [
            "muzzle_snds_H", 
            "muzzle_snds_L",
            "muzzle_snds_M",
            "muzzle_snds_B",
            "muzzle_snds_H_MG"
       ];

       _items = primaryWeaponItems player;

       {
            if (_x in _arr) then
            {
                 hint format ["Players Pri weapon has a %1", _x];
            };
       } forEach _items;

       _items = secondaryWeaponItems player;

       {
            if (_x in _arr) then
            {
                 hint format ["Players Sec weapon has a %1", _x];
            };
       } forEach _items; 

Thanks for your help.

cya.

Nikiller.

Share this post


Link to post
Share on other sites

Hi again,

Yup you're on the right lines thinking about event handlers :)

Try this - I wrote it just now. Detects all silencers (on the assumption that nothing else can be added to the barrel). I can change that though if needed.

It removes the silencer after 30 shots (you can switch weapons and it will still track on a per weapon-class basis).

For some reason I put secondary weapons in there (missile silencer ?!?) don't worry, it won't make any difference to how it works.

ALso, for anyone else reading - it doesn't track the bullets fired per silencer object. There is no way to do that in Arma 3. You need to play DayZ or something other game where weapons and their attachments are treated as entities for that to work.

Put the code in the debug box, init.sqf, or init line.

Let me know if there's any bugs, or if there's anything missing. If all is ok, I'll release it as a script :)

Crappy video:

player addEventHandler ["fired", {
_items = [];
_type = "none";
call {
	if (currentWeapon player == primaryWeapon player) exitWith {
		_items = primaryWeaponItems player;
		_type = "prim";
	};
	if (currentWeapon player == handGunWeapon player) exitWith {
		_items = handgunItems player;
		_type = "pist";
	};
	if (currentWeapon player == secondaryWeapon player) exitWith {
		_items = secondaryWeaponItems player;
		_type = "sec";
	};
};

if not (_items isEqualTo []) then {
	_silencers = getArray(configFile / "CfgWeapons" /currentWeapon player / "WeaponSlotsInfo" / "MuzzleSlot" / "compatibleitems");

	_silencer = "";
	{
		if (_x in _silencers) exitWith {
			_silencer = _x;
		};
	} forEach _items;

	if (_silencer != "") then {
		_found = false;
		_tabs = player getVariable ["tabs",[]];
		{
			_entry = _x;
			if (_silencer == (_entry select 0)) exitWith {
				_currentShots = _entry select 1;
				if (_currentShots < 29) then {
					_currentShots = _currentShots + 1;
					_tabs set [_forEachIndex,[_silencer,_currentShots]];
					player setVariable ["tabs",_tabs];
					_found = true;
				} else {
					call {
						if (_type == "prim") exitWith {
							player removePrimaryWeaponItem _silencer;
						};
						if (_type == "pist") exitWith {
							player removeHandGunItem _silencer;
						};
						if (_type == "sec") exitWith {
							player removeSecondaryWeaponItem _silencer;
						};
					};
					_tabs set [_forEachIndex,[_silencer,0]];
					player setVariable ["tabs",_tabs];
				};
			};
		} forEach _tabs;
		if not (_found) then {
			_tabs pushBack [_silencer,1];
			player setVariable ["tabs",_tabs];
		};
	};
};
}];

Share this post


Link to post
Share on other sites

It's not something you did wrong, it was me.

To find the silencer current count, I used the "in" command and forgot it was case sensitive. Some of the guns worked and others didn't and I didn't test them all so I didn't spot my mistake.

I've fixed it up so paste in the code below and all should be well.

Thanks for getting back to me with a test mission - helped me a lot :)

player addEventHandler ["fired", {
private ["_items","_type","_silencers","_silencer","_found","_tabs","_entry","_currentShots"];
_items = [];
_type = "none";
call {
	if (currentWeapon player == primaryWeapon player) exitWith {
		_items = primaryWeaponItems player;
		_type = "prim";
	};
	if (currentWeapon player == handGunWeapon player) exitWith {
		_items = handgunItems player;
		_type = "pist";
	};
	if (currentWeapon player == secondaryWeapon player) exitWith {
		_items = secondaryWeaponItems player;
		_type = "sec";
	};
};

if not (_items isEqualTo []) then {
	_silencers = getArray (configFile / "CfgWeapons" / currentWeapon player / "WeaponSlotsInfo" / "MuzzleSlot" / "compatibleitems");
	scopeName "scopey";
	_silencer = "";
	{
		_item = _x;
		{
			if (_x == _item) then {
				_silencer = _x;
				breakTo "scopey"
			};
		} forEach _silencers;
	} forEach _items;

	if (_silencer != "") then {
		_found = false;
		_tabs = player getVariable ["tabs",[]];
		{
			_entry = _x;
			if (_silencer == (_entry select 0)) exitWith {
				_currentShots = _entry select 1;
				if (_currentShots < 29) then {
					_currentShots = _currentShots + 1;
					_tabs set [_forEachIndex,[_silencer,_currentShots]];
					player setVariable ["tabs",_tabs];
					_found = true;
				} else {
					call {
						if (_type == "prim") exitWith {
							player removePrimaryWeaponItem _silencer;
						};
						if (_type == "pist") exitWith {
							player removeHandGunItem _silencer;
						};
						if (_type == "sec") exitWith {
							player removeSecondaryWeaponItem _silencer;
						};
					};
					_tabs set [_forEachIndex,[_silencer,0]];
					player setVariable ["tabs",_tabs];
					_found = true;
				};
			};
		} forEach _tabs;
		if not (_found) then {
			_tabs pushBack [_silencer,1];
			player setVariable ["tabs",_tabs];
		};
	};
};
}];

Share this post


Link to post
Share on other sites

hi,

I found what was wrong. I use addons and when I disabled it, it worked like charm. I will disable my addons one by one to find which one make the script bug (I suspect jsrs).

cya.

Nikiller.

EDIT: Seems not JSRS related I will investigate more but the issue is definitively not on the script side.

I will test it in MP with a lot of player to see if there's any problem (bugs, performance)

Thanks mate I really appreciate your help.

EDIT2: I have a suggestion:

I would be perfect if you could set a number of shots by type of silencer. Because 30 shots on an assault rifle is not much but 30 shots on sniper is a lot if you know what I mean.

Edited by Nikiller

Share this post


Link to post
Share on other sites

You need a cool metal breaking sound effect to go with it too!

Share this post


Link to post
Share on other sites

hi,

I found a solution, idk if it's the right way to do it but it works.

suppressorCheck.sqf by Das Attorney modified by Nikiller

player addEventHandler ["fired", {
   private ["_items","_type","_silencers","_silencer","_found","_tabs","_entry","_maxshots","_currentShots"];
   _items = [];
   _type = "none";
   call {
       if (currentWeapon player == primaryWeapon player) exitWith {
           _items = primaryWeaponItems player;
           _type = "prim";
       };
       if (currentWeapon player == handGunWeapon player) exitWith {
           _items = handgunItems player;
           _type = "pist";
       };
       if (currentWeapon player == secondaryWeapon player) exitWith {
           _items = secondaryWeaponItems player;
           _type = "sec";
       };
   };

   if not (_items isEqualTo []) then {
       _silencers = getArray (configFile / "CfgWeapons" / currentWeapon player / "WeaponSlotsInfo" / "MuzzleSlot" / "compatibleitems");
       scopeName "scopey";
       _silencer = "";
       {
           _item = _x;
           {
               if (_x == _item) then {
                   _silencer = _x;
                   breakTo "scopey"
               };
           } forEach _silencers;
       } forEach _items;

       if (_silencer != "") then {
           _found = false;
           _tabs = player getVariable ["tabs",[]];
           {
               _entry = _x;
               if (_silencer == (_entry select 0)) exitWith {
                   _currentShots = _entry select 1;
				if (_silencer == "muzzle_snds_B") then {_maxshots=30};
				if (_silencer == "muzzle_snds_H") then {_maxshots=60};
				if (_silencer == "muzzle_snds_M") then {_maxshots=90};
				if (_silencer == "muzzle_snds_L") then {_maxshots=120};
				if (_silencer == "muzzle_snds_H_MG") then {_maxshots=200};
                   if (_currentShots < _maxshots) then {
                       _currentShots = _currentShots + 1;
                       _tabs set [_forEachIndex,[_silencer,_currentShots]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   } else {
                       call {
                           if (_type == "prim") exitWith {
                               player removePrimaryWeaponItem _silencer;
                           };
                           if (_type == "pist") exitWith {
                               player removeHandGunItem _silencer;
                           };
                           if (_type == "sec") exitWith {
                               player removeSecondaryWeaponItem _silencer;
                           };
                       };
                       _tabs set [_forEachIndex,[_silencer,0]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   };
               };
           } forEach _tabs;
           if not (_found) then {
               _tabs pushBack [_silencer,1];
               player setVariable ["tabs",_tabs];
           };
       };
   };
}];

If you want to change the number of shots a silencer can fire change the _maxshots value. If you want to use addon you will have to include the addon silencer className.

Thanks again for the help.

cya.

Nikiller.

Share this post


Link to post
Share on other sites

Change it to this and the default will be 30.

EDIT: or the easier method. I should of thought of that first...

_maxshots = 30;
if (_silencer == "muzzle_snds_B") then {_maxshots=30};
if (_silencer == "muzzle_snds_H") then {_maxshots=60};
if (_silencer == "muzzle_snds_M") then {_maxshots=90};
if (_silencer == "muzzle_snds_L") then {_maxshots=120};
if (_silencer == "muzzle_snds_H_MG") then {_maxshots=200};

EDIT 2: You could also do it without classnames using BIS_fnc_itemType

_weapon = currentWeapon player;
_class = _weapon call BIS_fnc_itemType; // returns ["category","type"] ie ["Weapon","SubmachineGun"]

_maxShots = switch (toLower _class select 1) do {
case "assaultrifle": {30};
case "handgun": {60};
case "machinegun": {90};
case "shotgun": {20};
case "rifle": {30};
case "submachinegun": {60};
case "sniperrifle": {10};
case "launcher": {0};
};

Edited by Fight9

Share this post


Link to post
Share on other sites

Awesome guys - I was going to put something like that in but you've saved me a job - carry on! :)

Share this post


Link to post
Share on other sites

The problem with something like this is that the damage of the suppressor is on the player and not on the suppressor, so giving an almost broken suppressor to a buddy would result in him having a fully functional suppressor.

As far as I'm aware it is unfortunately not possible to setVariable on an item/weapon/attachment/magazine. You may wish to add a feedback tracker request (or find an existing one) for it and post a link so we can vote on it.

Share this post


Link to post
Share on other sites

I know the limitations - check the first post ;)

I don't think they could upgrade it within the product lifetime - they have done object based objects (!) with DayZ but that is a complete engine rewrite so I don't expect they would bother with Arma 3.

I just fancied doing a bit of coding to be honest, even if it does make magic regenerating suppressors! :)

Share this post


Link to post
Share on other sites

hi,

EDIT 2: You could also do it without classnames using BIS_fnc_itemType

_weapon = currentWeapon player;
_class = _weapon call BIS_fnc_itemType; // returns ["category","type"] ie ["Weapon","SubmachineGun"]

_maxShots = switch (toLower _class select 1) do {
case "assaultrifle": {30};
case "handgun": {60};
case "machinegun": {90};
case "shotgun": {20};
case "rifle": {30};
case "submachinegun": {60};
case "sniperrifle": {10};
case "launcher": {0};
};

I'm very interested by this method because it should work with any addons without modification. But unfortunately I can't make it work. Can you provide an example with the full script please?

cya.

Nikiller.

EDIT: Ok it didn't work since switch seems to be case sensitive.

By Fight9 modified by Nikiller.

					_maxShots = 30;
				_maxShots = switch (_class select 1) do {
				case "AssaultRifle": {120};
				case "Handgun": {150};
				case "MachineGun": {210};
				case "Shotgun": {60};
				case "Rifle": {90};
				case "SubmachineGun": {150};
				case "SniperRifle": {30};
				case "Launcher": {0};
				};  				

silencerCheck.sqf by Das Attorney modified by Nikiller.

player addEventHandler ["fired", {
   private ["_items","_type","_silencers","_silencer","_found","_tabs","_entry","_maxshots","_currentShots"];
   _items = [];
   _type = "none";
   call {
       if (currentWeapon player == primaryWeapon player) exitWith {
           _items = primaryWeaponItems player;
           _type = "prim";
       };
       if (currentWeapon player == handGunWeapon player) exitWith {
           _items = handgunItems player;
           _type = "pist";
       };
       if (currentWeapon player == secondaryWeapon player) exitWith {
           _items = secondaryWeaponItems player;
           _type = "sec";
       };
   };

   if not (_items isEqualTo []) then {
       _silencers = getArray (configFile / "CfgWeapons" / currentWeapon player / "WeaponSlotsInfo" / "MuzzleSlot" / "compatibleitems");
       scopeName "scopey";
       _silencer = "";
       {
           _item = _x;
           {
               if (_x == _item) then {
                   _silencer = _x;
                   breakTo "scopey"
               };
           } forEach _silencers;
       } forEach _items;

       if (_silencer != "") then {
           _found = false;
           _tabs = player getVariable ["tabs",[]];
           {
               _entry = _x;
               if (_silencer == (_entry select 0)) exitWith {
                   _currentShots = _entry select 1;
				_weapon = currentWeapon player;
				_class = _weapon call BIS_fnc_itemType; // returns ["category","type"] ie ["Weapon","SubmachineGun"]

				_maxShots = 30;
				_maxShots = switch (_class select 1) do {
				case "AssaultRifle": {120};
				case "Handgun": {150};
				case "MachineGun": {210};
				case "Shotgun": {60};
				case "Rifle": {90};
				case "SubmachineGun": {150};
				case "SniperRifle": {30};
				case "Launcher": {0};
				};  				

                   if (_currentShots < _maxShots) then {
                       _currentShots = _currentShots + 1;
                       _tabs set [_forEachIndex,[_silencer,_currentShots]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   } else {
                       call {
                           if (_type == "prim") exitWith {
                               player removePrimaryWeaponItem _silencer;
                           };
                           if (_type == "pist") exitWith {
                               player removeHandGunItem _silencer;
                           };
                           if (_type == "sec") exitWith {
                               player removeSecondaryWeaponItem _silencer;
                           };
                       };
                       _tabs set [_forEachIndex,[_silencer,0]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   };
               };
           } forEach _tabs;
           if not (_found) then {
               _tabs pushBack [_silencer,1];
               player setVariable ["tabs",_tabs];
           };
       };
   };
}];

Thanks everyone for the help.

Edited by Nikiller

Share this post


Link to post
Share on other sites

Yes, switch is case sensitive. I compensated for that in my original post by making everything lower case using the toLower command.

EDIT: removed new code, values were wrong and oyu already figured it out.

EDIT 2: I looked at your code again and the only thing wrong I see is the default for the switch. The way you have it now, the first value of 30 will be removed even if a different condition is found. You can use a default in the switch though.

_maxShots = switch (_class select 1) do {
case "AssaultRifle": {120};
case "Handgun": {150};
case "MachineGun": {210};
case "Shotgun": {60};
case "Rifle": {90};
case "SubmachineGun": {150};
case "SniperRifle": {30};
case "Launcher": {0};
default {30};
};    

Edited by Fight9

Share this post


Link to post
Share on other sites

Sorry for necro, but i tried using this script and am getting errors on line 4, im unsure if sth has changed since 2015 that nulifies the script, can anyone understand whats breaking it? Classnames all still seem valid.

 

player addEventHandler ["fired", {
   private ["_items","_type","_silencers","_silencer","_found","_tabs","_entry","_maxshots","_currentShots"];
   _items = [];
   _type = "none";
   call {
       if (currentWeapon player == primaryWeapon player) exitWith {
           _items = primaryWeaponItems player;
           _type = "prim";
       };
       if (currentWeapon player == handGunWeapon player) exitWith {
           _items = handgunItems player;
           _type = "pist";
       };
       if (currentWeapon player == secondaryWeapon player) exitWith {
           _items = secondaryWeaponItems player;
           _type = "sec";
       };
   };

   if not (_items isEqualTo []) then {
       _silencers = getArray (configFile / "CfgWeapons" / currentWeapon player / "WeaponSlotsInfo" / "MuzzleSlot" / "compatibleitems");
       scopeName "scopey";
       _silencer = "";
       {
           _item = _x;
           {
               if (_x == _item) then {
                   _silencer = _x;
                   breakTo "scopey"
               };
           } forEach _silencers;
       } forEach _items;

       if (_silencer != "") then {
           _found = false;
           _tabs = player getVariable ["tabs",[]];
           {
               _entry = _x;
               if (_silencer == (_entry select 0)) exitWith {
                   _currentShots = _entry select 1;
				_weapon = currentWeapon player;
				_class = _weapon call BIS_fnc_itemType; // returns ["category","type"] ie ["Weapon","SubmachineGun"]

				_maxShots = 30;
				_maxShots = switch (_class select 1) do {
				case "AssaultRifle": {120};
				case "Handgun": {150};
				case "MachineGun": {210};
				case "Shotgun": {60};
				case "Rifle": {90};
				case "SubmachineGun": {150};
				case "SniperRifle": {30};
				case "Launcher": {0};
				};  				

                   if (_currentShots < _maxShots) then {
                       _currentShots = _currentShots + 1;
                       _tabs set [_forEachIndex,[_silencer,_currentShots]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   } else {
                       call {
                           if (_type == "prim") exitWith {
                               player removePrimaryWeaponItem _silencer;
                           };
                           if (_type == "pist") exitWith {
                               player removeHandGunItem _silencer;
                           };
                           if (_type == "sec") exitWith {
                               player removeSecondaryWeaponItem _silencer;
                           };
                       };
                       _tabs set [_forEachIndex,[_silencer,0]];
                       player setVariable ["tabs",_tabs];
                       _found = true;
                   };
               };
           } forEach _tabs;
           if not (_found) then {
               _tabs pushBack [_silencer,1];
               player setVariable ["tabs",_tabs];
           };
       };
   };
}];

 

Share this post


Link to post
Share on other sites
1 minute ago, pierremgi said:

From where are you running this code?

from sqf, suppressorCheck.sqf

 

calling it via mission in it with 

[] execVM "suppressorCheck.sqf";

 

 

Share this post


Link to post
Share on other sites
9 hours ago, redarmy said:

getting errors on line 4,

What's the errors? Get into your .rpt log file and copy the error messages into a codebox here on the forum for better help 

Share this post


Link to post
Share on other sites
37 minutes ago, mrcurry said:

What's the errors? Get into your .rpt log file and copy the error messages into a codebox here on the forum for better help 

actually error was my fault,already fixed,however the script isnt working . No errors now but it just isnt removing suppressor after x amount of shots fired.

Share this post


Link to post
Share on other sites

Perhaps, you could try something simple as:

 

player setVariable ["MGI_cntSilencer",[10,3]];   // [global cnt for primary weapon, global cnt for hand gun]
player addEventHandler ["fired", {
    params ["_unit"];
    call {
        if (_unit weaponAccessories currentMuzzle _unit param [0, ""] != "") exitWith {
            _silencer = _unit weaponAccessories currentMuzzle _unit param [0, ""];
            call {
                if (currentWeapon _unit isEqualTo primaryWeapon _unit) exitWith {
                    _cntPrim = (_unit getVariable ["MGI_cntSilencer",[0,0]])#0;
                    _cntPrim = _cntPrim -1;
                    (_unit getVariable ["MGI_cntSilencer",[0,0]]) set [0,_cntPrim];
                    if (_cntPrim < 1) then {
                        _unit removePrimaryWeaponItem _silencer;
                    };
                };
                if (currentWeapon _unit isEqualTo handGunWeapon _unit) exitWith {
                    _cntHG = (_unit getVariable ["MGI_cntSilencer",[0,0]])#1;
                    _cntHG = _cntHG -1;
                    (_unit getVariable ["MGI_cntSilencer",[0,0]]) set [1,_cntHG];
                    if (_cntHG < 1) then {
                        _unit removeHandGunItem _silencer;
                    };
                };
            };
        };
    };
}];

 

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, pierremgi said:

Perhaps, you could try something simple as:

 


player setVariable ["MGI_cntSilencer",[10,3]];   // [global cnt for primary weapon, global cnt for hand gun]
player addEventHandler ["fired", {
    params ["_unit"];
    call {
        if (_unit weaponAccessories currentMuzzle _unit param [0, ""] != "") exitWith {
            _silencer = _unit weaponAccessories currentMuzzle _unit param [0, ""];
            call {
                if (currentWeapon _unit isEqualTo primaryWeapon _unit) exitWith {
                    _cntPrim = (_unit getVariable ["MGI_cntSilencer",[0,0]])#0;
                    _cntPrim = _cntPrim -1;
                    (_unit getVariable ["MGI_cntSilencer",[0,0]]) set [0,_cntPrim];
                    if (_cntPrim < 1) then {
                        _unit removePrimaryWeaponItem _silencer;
                    };
                };
                if (currentWeapon _unit isEqualTo handGunWeapon _unit) exitWith {
                    _cntHG = (_unit getVariable ["MGI_cntSilencer",[0,0]])#1;
                    _cntHG = _cntHG -1;
                    (_unit getVariable ["MGI_cntSilencer",[0,0]]) set [1,_cntHG];
                    if (_cntHG < 1) then {
                        _unit removeHandGunItem _silencer;
                    };
                };
            };
        };
    };
}];

 

that is working,however the issue is,that if i apply a "new" suppressor,it also gets remove,but after the first shot is fired. So the script is basically saying once player fires 10 shots,apply the removal of a suppressor. Im attempting to create a scenario with suppressor "durability". Its a Dayz type scenario where i want suppressors to be able to break after x amount of shots,but more suppressors are lootable in the world,if that makes sense.So essentially all handgun suppressors should last x amount of shots fired,and that info saved if i swapped weapons and then went back to the pistol etc etc.

 

Is there any way to combine your script and the above for that effect?

Share this post


Link to post
Share on other sites

The initial script above doesn't work, so, no!

The initial script above doesn't count shots by specific silencer. It's just supposed to expand the possibilities with type of silencers (MG, rifle, sniper rifle... ones).

It's easy to add these types if you tweak the setting of the variable.

It's not so easy to add a variable for specific silencer in player's loadout!

Silencers are items, so classes, neither objects nor identified like magazines are (for ammo count). They don't have such command as itemsDetail of course, as magazinesDetail exists.

If you want to tweak a pseudo-count for existing silencers in player's inventory, you can probably set a variable array... with no guarantee for picking the right silencer with the right count. A lot of work not avoiding cheating, imho.

Share this post


Link to post
Share on other sites
1 hour ago, pierremgi said:

The initial script above doesn't work, so, no!

The initial script above doesn't count shots by specific silencer. It's just supposed to expand the possibilities with type of silencers (MG, rifle, sniper rifle... ones).

It's easy to add these types if you tweak the setting of the variable.

It's not so easy to add a variable for specific silencer in player's loadout!

Silencers are items, so classes, neither objects nor identified like magazines are (for ammo count). They don't have such command as itemsDetail of course, as magazinesDetail exists.

If you want to tweak a pseudo-count for existing silencers in player's inventory, you can probably set a variable array... with no guarantee for picking the right silencer with the right count. A lot of work not avoiding cheating, imho.

I get what you mean now,yeah it would be alot of work with alotof classnames/testing. Il leave it alone and find another method of achieving the desired outcome,cheers for the help.

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

×