diff --git a/addons/events/CfgFunctions.hpp b/addons/events/CfgFunctions.hpp index 8b83e7d7c..4d19c0144 100644 --- a/addons/events/CfgFunctions.hpp +++ b/addons/events/CfgFunctions.hpp @@ -28,5 +28,11 @@ class CfgFunctions { PATHTO_FNC(registerChatCommand); PATHTO_FNC(weaponEvents); }; + + class Sounds { + PATHTO_FNC(executeWhenSoundWaveArrived); + PATHTO_FNC(playSound3D); + PATHTO_FNC(stopSound3D); + }; }; }; diff --git a/addons/events/XEH_preInit.sqf b/addons/events/XEH_preInit.sqf index 5e480a37b..3f606c3b4 100644 --- a/addons/events/XEH_preInit.sqf +++ b/addons/events/XEH_preInit.sqf @@ -27,6 +27,7 @@ if (isServer) then { #include "backwards_comp.sqf" #include "initSettings.sqf" +#include "initSounds.sqf" ADDON = true; diff --git a/addons/events/fnc_executeWhenSoundWaveArrived.sqf b/addons/events/fnc_executeWhenSoundWaveArrived.sqf new file mode 100644 index 000000000..f32aa8c0f --- /dev/null +++ b/addons/events/fnc_executeWhenSoundWaveArrived.sqf @@ -0,0 +1,65 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- + Function: CBA_fnc_executeWhenSoundWaveArrived + + Description: + Executes code snippet if sound from an origin has arrived at the camera. Local effects. + + Parameters: + _origin - Object or position from where sound emits + _code - Code to execute + _arguments - Additional arguments to pass to code, default [] + + Returns: + Nothing. + + Passed Arguments: + _origin - Same as above OR null object + _position - Current position of origin OR initial position + _arguments - Same as above + + Examples: + (begin example) + [cursorTarget, {playSound (_this select 2)}, "Alarm"] call CBA_fnc_executeWhenSoundWaveArrived; + (end) + + Author: + commy2 +---------------------------------------------------------------------------- */ + +if (!hasInterface) exitWith {}; + +params [ + ["_origin", cameraOn, [objNull, []], [3]], + ["_code", {}, [{}]], + ["_arguments", []] +]; + +[{ + params ["_code", "_origin", "_arguments", "_startTime"]; + + // Abort if origin of sound was deleted. + if (_origin isEqualTo objNull) exitWith { + true // quit + }; + + private _position = _origin; + if (_position isEqualType objNull) then { + _position = getPosASL _position; + } else { + _origin = objNull; + }; + + private _distanceToCamera = _position vectorDistance AGLToASL positionCameraToWorld [0,0,0]; + private _travelledDistance = (CBA_missionTime - _startTime) * SPEED_OF_SOUND; + + if (_distanceToCamera < _travelledDistance) exitWith { + [_origin, _position, _arguments] call _code; + + true // quit + }; + + false // continue +}, {}, [_code, _origin, _arguments, CBA_missionTime]] call CBA_fnc_waitUntilAndExecute; + +nil diff --git a/addons/events/fnc_playSound3D.sqf b/addons/events/fnc_playSound3D.sqf new file mode 100644 index 000000000..d02f50a16 --- /dev/null +++ b/addons/events/fnc_playSound3D.sqf @@ -0,0 +1,26 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- + Function: CBA_fnc_playSoundSOS + + Description: + Plays sound from object or position with speed of sound delay. Global effects. + + Parameters: + _origin - Object that emitted sound + _sound - CfgSounds class to play, rhs argument of say3D + + Returns: + Sound handler, used to stop the sound. + + Examples: + (begin example) + _handler = [cursorTarget, "Alarm"] call CBA_fnc_playSoundSOS; + + private _dummy = "#particlesource" createVehicleLocal [0,0,0]; + _dummy attachTo [tank1, [0,0,0], "memory_point"]; + [_dummy, "Alarm"] call CBA_fnc_playSoundSOS; + (end) + + Author: + commy2 +---------------------------------------------------------------------------- */ diff --git a/addons/events/fnc_stopSound3D.sqf b/addons/events/fnc_stopSound3D.sqf new file mode 100644 index 000000000..184e776cb --- /dev/null +++ b/addons/events/fnc_stopSound3D.sqf @@ -0,0 +1,21 @@ +#include "script_component.hpp" +/* ---------------------------------------------------------------------------- + Function: CBA_fnc_stopSoundSOS + + Description: + Stops sound from object or position with speed of sound delay. Global effects. + + Parameters: + _handler - Sound handler reported by CBA_fnc_playSoundSOS + + Returns: + Nothing. + + Examples: + (begin example) + _handler call CBA_fnc_stopSoundSOS; + (end) + + Author: + commy2 +---------------------------------------------------------------------------- */ diff --git a/addons/events/initSounds.sqf b/addons/events/initSounds.sqf new file mode 100644 index 000000000..d8d3fb281 --- /dev/null +++ b/addons/events/initSounds.sqf @@ -0,0 +1,131 @@ + +GVAR(activeSounds) = [] call CBA_fnc_createNamespace; + + + +/* + +if (hasInterface) then { + ["CBA_playSoundSOS", { + params ["_origin", "_sound", "_handler"]; + + GVAR(publicSounds) setVariable [_handler, [objNull, _origin]]; + + [_origin, { + params ["_origin", "", "_args"]; + _args params ["_sound", "_handler"]; + + private _source = allMissionObjects "#soundonvehicle"; + _origin say3D _sound; + _source = (allMissionObjects "#soundonvehicle" - _source) param [0, objNull]; + + GVAR(publicSounds) setVariable [_handler, [_source, _origin]]; + }, [_sound, _handler]] call CBA_fnc_executeWhenSoundWaveArrived; + }] call CBA_fnc_addEventHandler; + + ["CBA_stopSoundSOS", { + params ["_handler"]; + + (GVAR(publicSounds) getVariable [_handler, [nil, objNull]]) params ["", "_origin"]; + + [_origin, { + params ["", "", "_handler"]; + (GVAR(publicSounds) getVariable _handler) params ["_source"]; + + deleteVehicle _source; + }, _handler] call CBA_fnc_executeWhenSoundWaveArrived; + }] call CBA_fnc_addEventHandler; + + ["CBA_playSoundSOS_createDummy", { + params ["_origin", "_sound", "_handler"]; + + GVAR(publicSounds) setVariable [_handler, [objNull, _origin]]; + + [_origin, { + params ["_origin", "_position", "_args"]; + _args params ["_sound", "_handler"]; + + private _dummy = "#particlesource" createVehicleLocal ASLToAGL _position; + + if (!isNull _origin) then { + _dummy attachTo [_origin, [0,0,0]]; + }; + + private _source = allMissionObjects "#soundonvehicle"; + _dummy say3D _sound; + _source = (allMissionObjects "#soundonvehicle" - _source) param [0, objNull]; + + GVAR(publicSounds) setVariable [_handler, [_source, _origin]]; + + // Source is deleted by game if sound finished, manually delete dummy. + [{ + params ["_source"]; + isNull _source // return + }, { + params ["", "_dummy"]; + detach _dummy; + deleteVehicle _dummy; + }, [_source, _dummy]] call CBA_fnc_waitUntilAndExecute; + }, [_sound, _handler]] call CBA_fnc_executeWhenSoundWaveArrived; + }] call CBA_fnc_addEventHandler; + + ["CBA_playSoundSOSLooped", { + }] call CBA_fnc_addEventHandler; + + ["CBA_stopSoundSOSLooped", { + params ["_handler"]; + + (GVAR(publicSounds) getVariable [_handler, [nil, objNull]]) params ["", "_origin"]; + + [_origin, { + params ["", "", "_handler"]; + (GVAR(publicSounds) getVariable _handler) params ["_source", "_dummy"]; + + deleteVehicle _source; + deleteVehicle _dummy; + }, _handler] call CBA_fnc_executeWhenSoundWaveArrived; + }] call CBA_fnc_addEventHandler; +}; + +*/ + + +/*start +params [["_origin", objNull], ["_sound", "", ["", []]]]; + +if (!isNil QGVAR(publicSounds)) then { + GVAR(publicSounds) = [] call CBA_fnc_createNamespace; +}; + +private _id = (GVAR(publicSounds) getVariable ["#id", -1]) + 1; + +if (_id > 1E7) exitWith { + ERROR_1("Maximum amount of sound ids reached. Sound was %1.", _sound); + nil +}; + +GVAR(publicSounds) setVariable ["#id", _id]; + +private _handler = format ["%1:%2", CBA_clientID, _id]; + +if (_origin isEqualType objNull && {typeOf _origin isEqualTo ""}) then { + // Origin is dummy. + ["CBA_playSoundSOS", [_origin, _sound, _handler]] call CBA_fnc_globalEvent; +} else { + // Origin is position or proper object, @todo CfgAmmo? + ["CBA_playSoundSOS_createDummy", [_origin, _sound, _handler]] call CBA_fnc_globalEvent; +}; + +_handler + + + + + + +/*stop +params [["_handler", "empty", [""]]]; + +["CBA_stopSoundSOS", _handler] call CBA_fnc_globalEvent; + +nil diff --git a/addons/events/script_component.hpp b/addons/events/script_component.hpp index 15b59f33f..bec4185c5 100644 --- a/addons/events/script_component.hpp +++ b/addons/events/script_component.hpp @@ -51,3 +51,5 @@ #define MOUSE_OFFSET 0xF0 #define MOUSE_WHEEL_OFFSET 0xF8 // MOUSE_OFFSET + 8 possible mouse keys #define USERACTION_OFFSET 0xFA + +#define SPEED_OF_SOUND 343 // in meters per second