Robustcolor 30 Posted December 5, 2019 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
POLPOX 766 Posted December 5, 2019 _Aiunit addEventHandler ["hit",{ params ["_unit","","","_instigator"]; _hurt = selectRandom ["hurt1","hurt2","hurt3"]; if (_unit distance _instigator < 100) then { [_unit, _hurt] remoteExec ["say3D"]; }; }]; 2 Share this post Link to post Share on other sites
Robustcolor 30 Posted December 5, 2019 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
pierremgi 4739 Posted December 5, 2019 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]; 2 Share this post Link to post Share on other sites
Robustcolor 30 Posted December 5, 2019 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
pierremgi 4739 Posted December 5, 2019 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}))} 1 Share this post Link to post Share on other sites
Robustcolor 30 Posted December 5, 2019 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
Dedmen 2589 Posted December 6, 2019 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
Robustcolor 30 Posted December 6, 2019 @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
pierremgi 4739 Posted December 6, 2019 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; }; 1 Share this post Link to post Share on other sites
Robustcolor 30 Posted December 6, 2019 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
pierremgi 4739 Posted December 6, 2019 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. 1 Share this post Link to post Share on other sites
Robustcolor 30 Posted December 8, 2019 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
pierremgi 4739 Posted December 8, 2019 No... if you don't apply your EH on players. Share this post Link to post Share on other sites
Robustcolor 30 Posted December 8, 2019 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
GEORGE FLOROS GR 4206 Posted December 11, 2019 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