Jump to content
Robustcolor

Play sound when using HitHandler

Recommended Posts

Hi, i've tried different approaches here but i can't seem to get this to work. It does not play any sound at all when hitting the Ai unit.

 

The sounds are defined in cfgsounds / description.

_hurt =  selectRandom ["hurt1","hurt2","hurt3"];

_Aiunit addEventHandler ["hit",{
params ["_unit","","","_instigator"];

if (_unit distance _instigator < 100) then 
{
[_unit, _hurt] remoteExec ["say3D"];
};

}];

 

Share this post


Link to post
Share on other sites
_Aiunit addEventHandler ["hit",{
	params ["_unit","","","_instigator"];
	_hurt =  selectRandom ["hurt1","hurt2","hurt3"];
	if (_unit distance _instigator < 100) then 
	{
		[_unit, _hurt] remoteExec ["say3D"];
	};
}];

 

  • Like 2

Share this post


Link to post
Share on other sites
5 minutes ago, POLPOX said:

_Aiunit addEventHandler ["hit",{
	params ["_unit","","","_instigator"];
	_hurt =  selectRandom ["hurt1","hurt2","hurt3"];
	if (_unit distance _instigator < 100) then 
	{
		[_unit, _hurt] remoteExec ["say3D"];
	};
}];

 

Thanks @POLPOX It works now.

Share this post


Link to post
Share on other sites

Remark:

if (_unit distance _instigator < 100) then { [_unit, _hurt] remoteExec ["say3D"]; };

 literally means:  if the victim is near (within 100m) of the instigator, so any player, whatever his position must hear the "hurt".

 

I guess, you'd rather like:

if a player is near the victim, it should hear the "hurt", (whatever the distance from instigator)

So:

- as say3D is "Effect local", you need to remoteExec it if you didn't apply the EH "hit" on every client. (for example, _AiUnit is a spawned unit on server as I guess with the local variable). Nothing bad so far. For edited units, a simple this addEventHandler.... will do the job without remote execution.

 

- say3D has it's own "maxDistance" limitation (default:100m) So you don't need any more condition but write [_unit, [_hurt] ] remoteExec ["say3D"]; (2nd syntax)

 

- for general purpose, if you need to apply some code to a little group of selected players:

  private _selectedPlayers = allplayers select {<a condition here>};

  [<your params here>] remoteExec ["your command", _selectedPlayers];

 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks @pierremgi i will skip the if/ then in the handler since you said say3d has a limit of 100 meter. I guess for closer limit i'll use the if / then.

 

About allplayers select maybe i should add a inareaarray from the unit to only select the closest players?

Share this post


Link to post
Share on other sites

As far as say3D is concerned, just use the command parameter. You can set the distance max as shown in BIKI.

 

Yes for inAreaArray:

allPlayers inAreaArray [getpos _unit,35,35]

 

If you really want to focus on the closest player to _unit:

allPlayers select {_x distanceSqr _unit == (selectmin (allPlayers apply {_x distanceSqr _unit}))}

 

  • Like 1

Share this post


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

allPlayers select {_x distanceSqr _unit == (selectmin (allPlayers apply {_x distanceSqr _unit}))}

This is interesting. Is it possible to adjust max range for it?

 

If I do like this to the Aiunit, will it move to the closest player?

 

_target = allPlayers select {_x distanceSqr _Aiunit == (selectmin (allPlayers apply {_x distanceSqr _Aiunit}))};

 

_Aiunit doMove position _target;

Share this post


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

allPlayers select {_x distanceSqr _unit == (selectmin (allPlayers apply {_x distanceSqr _unit}))}

this code is terrible.

Say you have 10 players, you are executing distanceSqr 110 times, and for no need, if you expect allPlayers not to change you might aswell just do the selectMin once and store in a variable.

Or you go the obvious way, sort by distance and take the closest
 

private _playersDistances = allPlayers apply {[_x distanceSqr _unit, _x]};

_playersDistances sort true; //Sort ascending, lowest distance at front.
private _target = (_playerDistances select 0) select 1; //Take first element in array (closest player) and grab the unit from the array.

 

14 hours ago, Robustcolor said:

Is it possible to adjust max range for it?

is also easy to do with this variant

 

(_playerDistances select 0) params ["_distanceSqr", "_target"];

instead of "private _target =" that way you have the distance of the closest player, and the player object available. And can first do a check on the distance.

 

It might also be more efficient to limit distance first using inAreaArray and then put that reduced unit list through the apply/sort.

 

14 hours ago, Robustcolor said:

_target = allPlayers select {_x distanceSqr _Aiunit == (selectmin (allPlayers apply {_x distanceSqr _Aiunit}))}; 

 

_Aiunit doMove getPosATL _target;

That won't work, _target is an ARRAY of units, containing only a single unit. you cannot pass an array with a unit to getPos. You need to take the unit out first.

Share this post


Link to post
Share on other sites

@Dedmen Something like this?

private _all = (switchableUnits + playableUnits - entities "HeadlessClient_F") select {alive _x};

_all = _all inAreaArray [getPos _unit,500,500];

private _playerDistances = _all apply {[_x distanceSqr _unit, _x]};

_playerDistances sort true;

(_playerDistances select 0) params ["_distanceSqr", "_target"];

 

Share this post


Link to post
Share on other sites

If you are sure you are using headless client, then remove them. I guess you don't.

deads are already removed from playableUnits and switchableUnits .

 

private _listeners = ((switchableUnits + playableUnits inAreaArray [getPos _unit,500,500]) - [_unit]);
private _target = objNull;
if !(_listeners isEqualTo []) then {
  private _playerDistances = _listeners apply {[_x distanceSqr _unit,_x]};
  _playerDistances sort true;
  _target = _playerDistances #0#1;
};

 

 

 

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

When i finally feel like i'm understanding something about arma coding you drop a super cool code like that @pierremgi. Why is it necessary for the if equalto then?

 

#0#1 reference for?

Share this post


Link to post
Share on other sites

if !(_listeners isEqualTo []) then...   because:

- you don't want to have an error if no playable units is inside the area. In such case, _playerDistances is [] and _playerDistances select0 select1 fails. The ! is a syntax for not.

- there is no reason to continue a code in such case.

 

#0 .... is another syntax for select 0  .. with a little but important difference.

  • Like 1

Share this post


Link to post
Share on other sites
On 12/6/2019 at 4:42 PM, pierremgi said:

private _listeners = ((switchableUnits + playableUnits inAreaArray [getPos _unit,500,500]) - [_unit]);

Is it necessary to - [_unit]); at the end if the unit is just a spawned not playable Ai?

Share this post


Link to post
Share on other sites

Is it possible to play 2 sounds from one unit?. If i already have the unit talking i would like him to play a hurt sound if hit but then continue with the talk again.

[_Aiunit, _talk] remoteExec ["say3D"];

_Aiunit addEventHandler ["hit",{
params ["_unit"];
_hurt =  selectRandom ["hurt1","hurt2","hurt3"];

[_unit, _hurt] remoteExec ["say3D"];

}];

 

Share this post


Link to post
Share on other sites

Hello there Robustcolor !

 

You can use a #particlesource and delete this if it's interrupted , using a variable .

If i can later i'll try to add an example :

_particlesource = "#particlesource" createVehicle _pos;
		[[_particlesource,_array] remoteExec ["say3D"]];

- you can also attach the particlesource if you want.

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

×