nikiller 18 Posted January 30, 2015 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
das attorney 858 Posted January 30, 2015 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
nikiller 18 Posted January 31, 2015 hi, Thank you for your help but I can't make it work. Can you say me what am I doing wrong? I uploaded a demo mission if you want to have a look. http://www.mediafire.com/download/la4gl3pi8on91w8/demo_niki_silencer_degradation.Stratis.rar cya. Nikiller. Share this post Link to post Share on other sites
das attorney 858 Posted January 31, 2015 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
nikiller 18 Posted January 31, 2015 (edited) 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 January 31, 2015 by Nikiller Share this post Link to post Share on other sites
fight9 14 Posted January 31, 2015 You need a cool metal breaking sound effect to go with it too! Share this post Link to post Share on other sites
nikiller 18 Posted January 31, 2015 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
fight9 14 Posted January 31, 2015 (edited) 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 January 31, 2015 by Fight9 Share this post Link to post Share on other sites
das attorney 858 Posted January 31, 2015 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
galzohar 31 Posted February 1, 2015 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
das attorney 858 Posted February 1, 2015 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
nikiller 18 Posted February 1, 2015 (edited) 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 February 1, 2015 by Nikiller Share this post Link to post Share on other sites
fight9 14 Posted February 1, 2015 (edited) 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 February 1, 2015 by Fight9 Share this post Link to post Share on other sites
redarmy 422 Posted October 2, 2023 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
pierremgi 4906 Posted October 2, 2023 From where are you running this code? Share this post Link to post Share on other sites
redarmy 422 Posted October 2, 2023 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
mrcurry 511 Posted October 2, 2023 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
redarmy 422 Posted October 2, 2023 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
pierremgi 4906 Posted October 3, 2023 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; }; }; }; }; }; }]; 1 Share this post Link to post Share on other sites
redarmy 422 Posted October 3, 2023 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
pierremgi 4906 Posted October 3, 2023 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
redarmy 422 Posted October 3, 2023 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