Jump to content
DarkViper98

help with eventHandler please!

Recommended Posts

Hello, could someone help me to get the idea how to do this:

 

so, the problem is when I add event handler to a unit, f.e. FiredNear, it gets executed everytime someone is shot near and as it's said in Arma 3: Event Handlers page, also when unit fired itself. So how can i compensate that, to make a delay with some seconds to prevent unit spamming the code, which is inside the event handler? Or how can i use the time in event handler, because it's not working there, only if i use [] spawn function inside, but even using this method i can't get what i am needed. So this is the code: 

Spoiler

_soldier addEventHandler ["FiredNear", {
	
	_soldier = _this select 0;

	_soldiersWEST = allUnits select {side _x == WEST};	
	{_firer = _x;} forEach _soldiersWEST;	
	_firer = _this select 1;

	_WeaponFirer = primaryWeapon _firer;
	_WeaponFirer = _this select 3;
								
	_chanceSuppress = if ((random 100) >= 50) then {true} else {false};
	_soundToPlaySupress = ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"] call BIS_fnc_selectRandom;
	
	if ((primaryWeapon _firer == _WeaponFirer) && (_chanceSuppress) && (behaviour _soldier == 'COMBAT')) then {
	
		if (_firer distance _soldier > 25) then {
	
			if (alive _soldier) then {
				
				_unitsSuppress = units group _soldier;
				
				if (count _unitsSuppress <= 1) then {
				
					_chanceSuppress1 = if ((random 100) >= 75) then {true} else {false};
					if (_chanceSuppress1) then {
						_unit_first_supress = _unitsSuppress select 0;			
						_unit_first_supress say3D [_soundToPlaySupress, 100, 1];
					};
				};
				
				if (count _unitsSuppress >= 2) then {		
					_chanceSuppress2 = if ((random 100) >= 75) then {true} else {false};
					if (_chanceSuppress2)  then {
						_unit_random_suppress = _unitsSuppress select floor random count _unitsSuppress;			
						_unit_random_suppress say3D [_soundToPlaySupress, 100, 1];
					};
				};			
			};			
		};		
	};
}];

 

The sence is when someone is fired near it plays sound, but the problem is that when Ais are shooting a lot this is spammed incredible amount of times, how can i make a delay here, or a cooldown to prevent that... Or like this can be executed once for 15 seconds and so on...

Thank you so much for help

  • Like 1

Share this post


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

prevent unit spamming the code

 

Hello there DarkViper98 and welcome also to BI Forums !

 

Maybe you should take a look in here :

 

Share this post


Link to post
Share on other sites
16 hours ago, DarkViper98 said:

Hello, could someone help me to get the idea how to do this:

 

so, the problem is when I add event handler to a unit, f.e. FiredNear, it gets executed everytime someone is shot near and as it's said in Arma 3: Event Handlers page, also when unit fired itself. So how can i compensate that, to make a delay with some seconds to prevent unit spamming the code, which is inside the event handler? Or how can i use the time in event handler, because it's not working there, only if i use [] spawn function inside, but even using this method i can't get what i am needed. So this is the code: 

  Hide contents


_soldier addEventHandler ["FiredNear", {
	
	_soldier = _this select 0;

	_soldiersWEST = allUnits select {side _x == WEST};	
	{_firer = _x;} forEach _soldiersWEST;	
	_firer = _this select 1;

	_WeaponFirer = primaryWeapon _firer;
	_WeaponFirer = _this select 3;
								
	_chanceSuppress = if ((random 100) >= 50) then {true} else {false};
	_soundToPlaySupress = ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"] call BIS_fnc_selectRandom;
	
	if ((primaryWeapon _firer == _WeaponFirer) && (_chanceSuppress) && (behaviour _soldier == 'COMBAT')) then {
	
		if (_firer distance _soldier > 25) then {
	
			if (alive _soldier) then {
				
				_unitsSuppress = units group _soldier;
				
				if (count _unitsSuppress <= 1) then {
				
					_chanceSuppress1 = if ((random 100) >= 75) then {true} else {false};
					if (_chanceSuppress1) then {
						_unit_first_supress = _unitsSuppress select 0;			
						_unit_first_supress say3D [_soundToPlaySupress, 100, 1];
					};
				};
				
				if (count _unitsSuppress >= 2) then {		
					_chanceSuppress2 = if ((random 100) >= 75) then {true} else {false};
					if (_chanceSuppress2)  then {
						_unit_random_suppress = _unitsSuppress select floor random count _unitsSuppress;			
						_unit_random_suppress say3D [_soundToPlaySupress, 100, 1];
					};
				};			
			};			
		};		
	};
}];

 

The sence is when someone is fired near it plays sound, but the problem is that when Ais are shooting a lot this is spammed incredible amount of times, how can i make a delay here, or a cooldown to prevent that... Or like this can be executed once for 15 seconds and so on...

Thank you so much for help

So you basically want a temporary timed lockout within the eventhandler, so it only fires at most every n seconds?

 

Your snippet could also use a good amount of simplification and a few adjustments.

It's usually best practice to put the most likely exit condition at the top and only continue the script if it doesn't apply.

Also in this case you really don't need an alive check, since dead units can't say stuff through the say/say3D/say2D commands.

 

I'm also not sure if you understand the firedNear EH, it only gets executed when someone within ~69m of the EH unit is using a weapon, not if anyone is getting shot at, at least that's what I think you expect from the EH, judging by your first paragraph.

What exactly are you expecting from this:

{_firer = _x;} forEach _soldiersWEST;	
_firer = _this select 1;

The second line makes the first one obsolete.

 

Same here:

_WeaponFirer = primaryWeapon _firer;
_WeaponFirer = _this select 3;

 

You can also simplify this:

_chanceSuppress = if ((random 100) >= 50) then {true} else {false};
//should be expressed like this:
_chanceSuppress = random 100 >= 50;

There's also no need to compare primaryWeapon _firer to _Weaponfirer, since this will essentially be the same.

 

This check is also rather obsolete, since a unit will always belong to a group unless you  designate  it to grpNull:

if (count _unitsSuppress <= 1) then {

You can use an exitWith condition and exit with the say for a single unit, if the group only holds one unit, depends on how you want this to play out, easy enough to modify it to your needs, heh.

 

Here's a tidied up version:

TAG_fnc_suppressSound = {
	params ["_unit"];
	sleep random [0.8,1.2,1.8];
	_unit say3D [selectRandom ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"], 100, 1]
};

_soldier addEventHandler ["FiredNear", {
	params ["_soldier","_firer","","_WeaponFirer"];

	if (side _soldier isEqualTo side _firer) exitWith {false};//remove this if needed
	_chanceSuppress = random 100 >= 50;
	if !(_chanceSuppress) exitWith {false};
	_unitsSuppress = units group _soldier;
	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};
	if (random 100 >= 75)  then {
		(selectRandom _unitsSuppress) spawn TAG_fnc_suppressSound;
	};
}];

This will play the suppression sound after a short delay to simulate human reaction time.

Now for the timed lockout to prevent spam you can do something like this:

TAG_fnc_suppressSound = {
	params ["_unit"];
	sleep random [0.8,1.2,1.8];
	_unit say3D [selectRandom ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"], 100, 1]
};

_soldier addEventHandler ["FiredNear", {
	params ["_soldier","_firer","","_WeaponFirer"];

	_lockoutTime = group _soldier getVariable ["TAG_fnc_suppressLockout",-10];
	if (time < _lockoutTime) exitWith {false};
	group _soldier setVariable ["TAG_fnc_suppressLockout",time + random [8,12,15]];

	if (side _soldier isEqualTo side _firer) exitWith {false};//remove this if needed
	if (random 100 <= 50) exitWith {false};
	_unitsSuppress = units group _soldier;
	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};
	if (random 100 >= 75)  then {
		(selectRandom _unitsSuppress) spawn TAG_fnc_suppressSound;
	};
}];

This will exit the EH if the lockout is still active, so it will only activate between every 8-15 seconds after last activation.

You can  adjust the frequency with the "random [8,12,15]" bit, the values being min,mid,max. In this case it will average around 12.

I also put the sound stuff in its own function.

 

Should get you started, though I think firedNear is the wrong EH for something like this.

 

Cheers

  • Like 2

Share this post


Link to post
Share on other sites
5 hours ago, Grumpy Old Man said:

So you basically want a temporary timed lockout within the eventhandler, so it only fires at most every n seconds?

 

Your snippet could also use a good amount of simplification and a few adjustments.

It's usually best practice to put the most likely exit condition at the top and only continue the script if it doesn't apply.

Also in this case you really don't need an alive check, since dead units can't say stuff through the say/say3D/say2D commands.

 

I'm also not sure if you understand the firedNear EH, it only gets executed when someone within ~69m of the EH unit is using a weapon, not if anyone is getting shot at, at least that's what I think you expect from the EH, judging by your first paragraph.

What exactly are you expecting from this:


{_firer = _x;} forEach _soldiersWEST;	
_firer = _this select 1;

The second line makes the first one obsolete.

 

Same here:


_WeaponFirer = primaryWeapon _firer;
_WeaponFirer = _this select 3;

 

You can also simplify this:


_chanceSuppress = if ((random 100) >= 50) then {true} else {false};
//should be expressed like this:
_chanceSuppress = random 100 >= 50;

There's also no need to compare primaryWeapon _firer to _Weaponfirer, since this will essentially be the same.

 

This check is also rather obsolete, since a unit will always belong to a group unless you  designate  it to grpNull:


if (count _unitsSuppress <= 1) then {

You can use an exitWith condition and exit with the say for a single unit, if the group only holds one unit, depends on how you want this to play out, easy enough to modify it to your needs, heh.

 

Here's a tidied up version:


TAG_fnc_suppressSound = {
	params ["_unit"];
	sleep random [0.8,1.2,1.8];
	_unit say3D [selectRandom ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"], 100, 1]
};

_soldier addEventHandler ["FiredNear", {
	params ["_soldier","_firer","","_WeaponFirer"];

	if (side _soldier isEqualTo side _firer) exitWith {false};//remove this if needed
	_chanceSuppress = random 100 >= 50;
	if !(_chanceSuppress) exitWith {false};
	_unitsSuppress = units group _soldier;
	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};
	if (random 100 >= 75)  then {
		(selectRandom _unitsSuppress) spawn TAG_fnc_suppressSound;
	};
}];

This will play the suppression sound after a short delay to simulate human reaction time.

Now for the timed lockout to prevent spam you can do something like this:


TAG_fnc_suppressSound = {
	params ["_unit"];
	sleep random [0.8,1.2,1.8];
	_unit say3D [selectRandom ["suppress1", "suppress2", "suppress3", "suppress4", "suppress5"], 100, 1]
};

_soldier addEventHandler ["FiredNear", {
	params ["_soldier","_firer","","_WeaponFirer"];

	_lockoutTime = group _soldier getVariable ["TAG_fnc_suppressLockout",-10];
	if (time < _lockoutTime) exitWith {false};
	group _soldier setVariable ["TAG_fnc_suppressLockout",time + random [8,12,15]];

	if (side _soldier isEqualTo side _firer) exitWith {false};//remove this if needed
	if (random 100 <= 50) exitWith {false};
	_unitsSuppress = units group _soldier;
	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};
	if (random 100 >= 75)  then {
		(selectRandom _unitsSuppress) spawn TAG_fnc_suppressSound;
	};
}];

This will exit the EH if the lockout is still active, so it will only activate between every 8-15 seconds after last activation.

You can  adjust the frequency with the "random [8,12,15]" bit, the values being min,mid,max. In this case it will average around 12.

I also put the sound stuff in its own function.

 

Should get you started, though I think firedNear is the wrong EH for something like this.

 

Cheers

Thank you very much for help, I am a beginner, that's the code i was able to write myself using a little amount of knowledge of sqf))) Some explanations: 

	_soldiersWESTarray = allUnits select {side _x == WEST};	
	{_soldierWEST = _x;} forEach _soldiersWESTarray;	

i write it to make the game understand to call the event handler if enemies from side WEST shooting, cus it can be called if _soldiers guys are shooting also. But you find more logical decision like :

if (side _soldier isEqualTo side _firer) exitWith {false};

That's very cool )) Thank you!!! Also about cheking the _firer weapon, i just forgot to remove that, cus after i read the EH again i got that. Want to ask some questions about this:

	_lockoutTime = group _soldier getVariable ["TAG_fnc_suppressLockout",-10];
	if (time < _lockoutTime) exitWith {false};
	group _soldier setVariable ["TAG_fnc_suppressLockout",time + random [6,8,13]];

So this code gets variables TAG_fnc_suppressLockout from soldiers group but what is -10 here? Is it like seconds?

Next line is: if time is less than _lockoutTime then stop the code. - OK

last: setting the variable with time (is this like a timer that counts? like it's said on wiki: Returns time elapsed since mission started (in seconds).). So we pick here a random time cooldown? Please explain how's that work, can't catch that a bit (((

 

Thank you!

Share this post


Link to post
Share on other sites
18 minutes ago, DarkViper98 said:

So this code gets variables TAG_fnc_suppressLockout from soldiers group but what is -10 here? Is it like seconds?

Next line is: if time is less than _lockoutTime then stop the code. - OK

last: setting the variable with time (is this like a timer that counts? like it's said on wiki: Returns time elapsed since mission started (in seconds).). So we pick here a random time cooldown? Please explain how's that work, can't catch that a bit (((

The variable TAG_fnc_suppressLockout holds the time from which the script shall continue again. -10 is used as a cautionary measure, allowing the script to work at mission start. It's basically the init value.

 

The variable time basically holds the runtime of the mission, starting with 0 at mission start.

Assuming the mission is running for exactly 5 minutes (300s) and random [6,8,13]  returns 7.5, the EH will exit until time returns more than 307.5.

 

Cheers

 

  • Like 1

Share this post


Link to post
Share on other sites
9 minutes ago, Grumpy Old Man said:

The variable TAG_fnc_suppressLockout holds the time from which the script shall continue again. -10 is used as a cautionary measure, allowing the script to work at mission start. It's basically the init value.

 

The variable time basically holds the runtime of the mission, starting with 0 at mission start.

Assuming the mission is running for exactly 5 minutes (300s) and random [6,8,13]  returns 7.5, the EH will exit until time returns more than 307.5.

 

Cheers

 

okayyy, also, never seen this:

	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};

_unitsSuppress#0 is this #0 instead of this select 0 or what? Like we are selecting soldier 1 from group array ? Thank you!

Share this post


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

okayyy, also, never seen this:


	if (count _unitsSuppress isEqualTo 1) then {
		if (random 100 >= 75) then {
			(_unitsSuppress#0) spawn TAG_fnc_suppressSound;
		};
	};

_unitsSuppress#0 is this #0 instead of this select 0 or what? Like we are selecting soldier 1 from group array ? Thank you!

It's basically select without enhanced syntax but higher precedence.

Pretty neat for better readability.

 

Cheers

Share this post


Link to post
Share on other sites
On 2/20/2020 at 5:57 PM, Grumpy Old Man said:

It's basically select without enhanced syntax but higher precedence.

Pretty neat for better readability.

 

Cheers

But is there a way to count how many times did EH executed? Like f.e. to count how many shots did the player, like is it's more that 3, to execute the code... Thank you!

Share this post


Link to post
Share on other sites
3 hours ago, DarkViper98 said:

But is there a way to count how many times did EH executed? Like f.e. to count how many shots did the player, like is it's more that 3, to execute the code... Thank you!

You can easily track shots via fired EH and use setVariable to store them, same principle as above applies here, just use the shots for the lockout instead of the time.

 

Cheers

  • 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

×