 sreV                prefix idi\acre\addons\sys_external  CfgEventHandlers.hpp                 CfgVehicles.hpp     ’          ’  config.bin     h          h  fnc_allowExternalUse.sqf                 fnc_checkListChildrenActions.sqf     ô          ô  fnc_checkReturnGive.sqf     /          /  fnc_childrenActions.sqf     Q          Q  fnc_externalRadioPFH.sqf                 fnc_getExternalRadioOwner.sqf     '          '  fnc_getExternalRadioUser.sqf     é          é  fnc_getExternalUseStatus.sqf     a          a  fnc_getSharedExternalRadios.sqf     £          £  fnc_initRadio.sqf     ‡          ‡  fnc_isExternalActionAvailable.sqf     }          }  fnc_isExternalRadioAvailable.sqf     Í          Í  fnc_isExternalRadioUsed.sqf     Ö          Ö  fnc_isRadioShared.sqf     ¾          ¾  fnc_listChildrenActions.sqf     5          5  fnc_onPlayerKilled.sqf     ™          ™  fnc_radioCheckChildrenActions.sqf     é          é  fnc_startUsingExternalRadio.sqf     -          -  fnc_stopUsingExternalRadio.sqf     R          R  script_component.hpp     ÷          ÷  stringtable.xml     g'          g'  XEH_postInit.sqf     |          |  XEH_preInit.sqf     ‹           ‹   XEH_PREP.hpp     ,          ,  XEH_preStart.sqf     <           <                        class Extended_PreStart_EventHandlers {
    class ADDON {
        init = QUOTE(call COMPILE_FILE(XEH_preStart));
    };
};

class Extended_PreInit_EventHandlers {
    class ADDON {
        init = QUOTE(call COMPILE_FILE(XEH_preInit));
    };
};

class Extended_PostInit_EventHandlers {
    class ADDON {
        init = QUOTE(call COMPILE_FILE(XEH_postInit));
    };
};

class Extended_Killed_EventHandlers {
    class Man {
        ADDON = QUOTE(_this call FUNC(onPlayerKilled));
    };
};
class CfgVehicles {
    class Man;
    class CAManBase: Man {
        class ACE_Actions {
            class ACE_MainActions {
                class ACRE_Interact_External {
                    displayName = CSTRING(externalRadios);
                    condition = QUOTE(_this call FUNC(isExternalActionAvailable));
                    exceptions[] = {"isNotInside", "isNotSitting"};
                    statement = "true";
                    insertChildren = QUOTE(_this call FUNC(listChildrenActions));
                    priority = 0.1;
                    icon = ICON_RADIO_CALL;
                };
            };
        };
    };
};
 raP       d    CfgPatches Ä    CfgVehicles ÿ   Extended_PreStart_EventHandlers ¦   Extended_PreInit_EventHandlers     Extended_PostInit_EventHandlers ™   Extended_Killed_EventHandlers     acre_sys_external Ý     name ACRE2 - External Radios units  weapons  requiredVersion ®G@requiredAddons  acre_main  acre_sys_core  acre_sys_data  author $STR_acre_main_Author authors  TheMagnetar  Snippers  url $STR_acre_main_URL version š™9@ versionStr 2.9.0.1042 versionAr    	          Man  CAManBase   Man  ACE_Actions +    ACE_MainActions B    ACRE_Interact_External `    displayName $STR_acre_sys_external_externalRadios  condition _this call acre_sys_external_fnc_isExternalActionAvailable exceptions  isNotInside  isNotSitting  statement true  insertChildren _this call acre_sys_external_fnc_listChildrenActions priority ÍÌÌ= icon \a3\Ui_f\data\GUI\Cfg\CommunicationMenu\call_ca.paa   acre_sys_external ¿    init call compile preprocessFileLineNumbers '\idi\acre\addons\sys_external\XEH_preStart.sqf'   acre_sys_external 9    init call compile preprocessFileLineNumbers '\idi\acre\addons\sys_external\XEH_preInit.sqf'   acre_sys_external ²    init call compile preprocessFileLineNumbers '\idi\acre\addons\sys_external\XEH_postInit.sqf'   Man     acre_sys_external _this call acre_sys_external_fnc_onPlayerKilled     #include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Mark a radio in order to enable/disable to be used by other units (external use).
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 * 1: Enable or disable sharing <BOOL>
 *
 * Return Value:
 * None
 *
 * Example:
 * ["ACRE_PRC343_ID_1", false] call acre_sys_external_fnc_allowExternalUse
 *
 * Public: No
 */

params ["_radioId", "_allowExternalUse"];

[_radioId, "setState", ["radioShared", _allowExternalUse]] call EFUNC(sys_data,dataEvent);
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Check if a given action is available for a specific radio and unit.
 *
 * Arguments:
 * 0: Unique radio ID <STRING>
 * 1: Unit to be checked <OBJECT>
 *
 * Return Value:
 * Action is available <BOOL>
 *
 * Example:
 * [cursorTarget] call acre_sys_external_fnc_checkListChildrenActions
 *
 * Public: No
 */

params ["_radioId", "_unit"];

private _isAvailable = true;

// Params are _isShared, _isUsedExternally, _owner and _user)
([_radioId] call FUNC(getExternalUseStatus)) params ["", "_isUsedExternally", "", "_user"];

// Do not allow an external user to return the headset if the radio is in use
if (_isUsedExternally && {_unit != _user}) exitWith {false};

// Prevent from taking a radio that can be also heard through the intercom or directly accessible racks
if ([_radioId, _unit] call EFUNC(sys_rack,isRadioHearable) || {[_radioId, _unit] call EFUNC(sys_rack,isRadioAccessible)}) exitWith {false};

_isAvailable
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Check if a radio being used externally is being returned to the owner or given to another unit.
 *
 * Arguments:
 * 1: Unique radio ID <STRING>
 * 0: Unit to be given/returned a radio <OBJECT>
 *
 * Return Value:
 * Radio is returned (true) or given (false) <BOOL>
 *
 * Example:
 * [cursorTarget] call acre_sys_external_fnc_checkReturnGive
 *
 * Public: No
 */

params ["_radioId", "_target"];

private _owner = [_radioId] call FUNC(getExternalRadioOwner);

_owner == _target
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Generates a list of actions for using a radio externaly.
 *
 * Arguments:
 * 0: Unit with a shared radio <OBJECT>
 * 1: None <TYPE>
 * 2: Array with additional parameters <ARRAY>
 *   0: Unique radio ID <STRING>
 *
 * Return Value:
 * Array of actions <ARRAY>
 *
 * Example:
 * [cursorTarget, "", ["ACRE_PRC343_ID_1"]] call acre_sys_external_fnc_childrenActions
 *
 * Public: No
 */

params ["_target", "", "_params"];
_params params ["_radio"];

private _actions = [];
private _playerOwnsRadio = acre_player == [_radio] call FUNC(getExternalRadioOwner);

if (_playerOwnsRadio) then {
    private _string =  localize LSTRING(giveHeadset);
    if ([_radio] call EFUNC(sys_radio,isManpackRadio)) then {
        _string = localize LSTRING(giveHandset)
    };
    private _action = [
        QGVAR(giveRadio),
        _string,
        "",
        {[_this select 2, _target] call FUNC(stopUsingExternalRadio)},
        {!([_this select 2] call FUNC(isExternalRadioUsed))},
        {},
        _radio
    ] call ace_interact_menu_fnc_createAction;
    _actions pushBack [_action, [], _target];
} else {
    private _string =  localize LSTRING(takeHeadset);
    if ([_radio] call EFUNC(sys_radio,isManpackRadio)) then {
        _string =  localize LSTRING(takeHandset)
    };
    private _action = [
        QGVAR(useRadio),
        _string,
        "",
        {[_this select 2, acre_player] call FUNC(startUsingExternalRadio)},
        {!([_this select 2] call FUNC(isExternalRadioUsed))},
        {},
        _radio
    ] call ace_interact_menu_fnc_createAction;
    _actions pushBack [_action, [], _target];
};

// Check if we are giving or returning the headset
if ([_radio, _target] call FUNC(checkReturnGive)) then {
    private _string =  localize LSTRING(returnHeadset);
    if ([_radio] call EFUNC(sys_radio,isManpackRadio)) then {
        _string =  localize LSTRING(returnHandset)
    };
    private _action = [
        QGVAR(returnRadio),
        _string,
        "",
        {[_this select 2, _target] call FUNC(stopUsingExternalRadio)},
        {[_this select 2] call FUNC(isExternalRadioUsed)},
        {},
        _radio
    ] call ace_interact_menu_fnc_createAction;
    _actions pushBack [_action, [], _target];
} else {
    private _string =  localize LSTRING(giveHeadset);
    if ([_radio] call EFUNC(sys_radio,isManpackRadio)) then {
        _string = localize LSTRING(giveHandset)
    };
    private _action = [
        QGVAR(giveRadio),
        _string,
        "",
        {[_this select 2, _target] call FUNC(stopUsingExternalRadio)},
        {[_this select 2] call FUNC(isExternalRadioUsed)},
        {},
        _radio
    ] call ace_interact_menu_fnc_createAction;
    _actions pushBack [_action, [], _target];
};

_actions
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Eventhandler to monitor if external radios can be still used by a specific player.
 *
 * - Disabled uses of external radios are:
 *   - Radio is in players inventory.
 *   - Distance between owner and end user is greater than 2m.
 *   - Owner and end user are not in the same vehicle.
 *   - Death of player is handled in fnc_onPlayerKilled.sqf.
 * - Radios in dead or captive units can always be accessed by other players.
 *
 * Arguments:
 * None
 *
 * Return Value:
 * None
 *
 * Example:
 * [] call acre_sys_external_fnc_externalRadioPFH
 *
 * Public: No
 */

/* TODO:
 * - Consider further corner cases.
 */

if (alive acre_player) then {
    // Check if we need to remove active radios
    private _radios = [acre_player] call EFUNC(sys_core,getGear);
    {
        // Remove radios that are in unit's inventory or match a certain criteria.
        private _owner = [_x] call FUNC(getExternalRadioOwner);
        private _isExternalRadioAvailable = [_x, _owner] call FUNC(isExternalRadioAvailable);
        if (!_isExternalRadioAvailable || {_x in _radios}) then {
            [_x, _owner] call FUNC(stopUsingExternalRadio);
        };
    } forEach ACRE_ACTIVE_EXTERNAL_RADIOS;
};
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Retrieves the owner of a radio that is being used externally.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * Radio owner (objNull if not in external use) <OBJECT>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_getExternalRadioOwner
 *
 * Public: No
 */

params ["_radioId"];

private _owner = [_radioId] call EFUNC(sys_radio,getRadioObject);

if !(_owner isKindOf "CAManBase") then {
    _owner = objNull;
};

_owner
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Retrieves the end user of a radio that is being used externally.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * End user (objNull if not in external use) <OBJECT>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_getExternalRadioUser
 *
 * Public: No
 */

params ["_radioId"];

[_radioId, "getState", "radioUsedExternally"] call EFUNC(sys_data,dataEvent) select 1
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Retrieves the external use status of a radio.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * Array with external use information <ARRAY>
 *   0: Shared <BOOL>
 *   1: In external use <BOOL>
 *   2: Owner <OBJECT>
 *   3: User <OBJECT>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_getExternalUseStatus
 *
 * Public: No
 */

params ["_radioId"];

private _isShared = [_radioId] call FUNC(isRadioShared);

private _owner = objNull;
private _user = objNull;

private _isUsedExternally = [_radioId] call FUNC(isExternalRadioUsed);
if (_isUsedExternally) then {
    _owner = [_radioId] call FUNC(getExternalRadioOwner);
    _user = [_radioId] call FUNC(getExternalRadioUser);
};

[_isShared, _isUsedExternally, _owner, _user]
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Returns a list of radios that are being shared by a unit.
 *
 * Arguments:
 * 0: Unit <OBJECT>
 *
 * Return Value:
 * Array of ACRE2 unique radio IDs that are flagged as shared <ARRAY>
 *
 * Example:
 * [cursorTarget] call acre_sys_external_fnc_getSharedExternalRadios
 *
 * Public: No
 */

params ["_unit"];

private _radios = [_unit] call EFUNC(sys_core,getGear);
private _radioList = _radios select {_x call EFUNC(sys_radio,isUniqueRadio)};

if (!(alive _unit) || {captive _unit}) exitWith {_radioList};

_radioList select {[_x, "getState", "radioShared"] call EFUNC(sys_data,dataEvent)}
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Initialises a radio with the additional states: isShared and isUsedExternally.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * None
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_initRadio
 *
 * Public: No
 */

params ["_radioId"];

[_radioId, false] call FUNC(allowExternalUse);
[_radioId, "setState", ["radioUsedExternally", [false, objNull]]] call EFUNC(sys_data,dataEvent);

// To prevent the GUI from being simultaneously opened
[_radioId, "setState", ["radioGuiOpened", false]] call EFUNC(sys_data,dataEvent);
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Checks if the player can perform external actions on shared radios.
 *
 * Arguments:
 * 0: Infantry unit <OBJECT>
 *
 * Return Value:
 * Can interact with external radios <BOOL>
 *
 * Example:
 * [cursorTarget] call acre_sys_external_fnc_isExternalRadioAvailable
 *
 * Public: No
 */

params ["_target"];

// Check first distance to the unit
if ((_target distance acre_player) > EXTERNAL_RADIO_MAXDISTANCE) exitWith {false};

// Action is available if the unit has shared radios.
private _sharedRadios = [_target] call FUNC(getSharedExternalRadios);
private _radiosInUse = _sharedRadios select {[_x] call FUNC(isExternalRadioUsed)};

// Of those radios that are in use, only the ones used by the player count
{
    if (acre_player != [_x] call FUNC(getExternalRadioUser))  then {
        _sharedRadios deleteAt (_sharedRadios find _x);
    };
} forEach _radiosInUse;

// If the player has external radios in use, the action to give or return radios should be also available
(_sharedRadios isNotEqualTo []) || {ACRE_ACTIVE_EXTERNAL_RADIOS isNotEqualTo []}
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Checks if a radio is externally available to the player.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 * 1: Radio owner <OBJECT>
 *
 * Return Value:
 * Radio is available for external use <BOOL>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_isExternalRadioAvailable
 *
 * Public: No
 */

/* TODO:
 * - Consider further corner cases.
 */

params ["_radioId", "_owner"];

// Check if actual owner of the radio is less than 2.0m away.
if (((_owner distance acre_player) > EXTERNAL_RADIO_MAXDISTANCE) && {vehicle _owner != vehicle acre_player}) exitWith {false};

// Captive players are not allowed to use external radios
if (captive acre_player) exitWith {false};

// Check if actual owner of the radio and the player are on the same vehicle.
!((vehicle _owner != _owner) && {vehicle acre_player != acre_player} && {vehicle _owner != vehicle acre_player})
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Checks if a radio is flagged as being used by another unit.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * Radio is being externally used <BOOL>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_isExternalRadioUsed
 *
 * Public: No
 */

params ["_radioId"];

[_radioId, "getState", "radioUsedExternally"] call EFUNC(sys_data,dataEvent) select 0
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Checks if a radio is shared to other players.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 *
 * Return Value:
 * Radio is shared and ready for external use <BOOL>
 *
 * Example:
 * ["ACRE_PRC343_ID_1"] call acre_sys_external_fnc_isRadioShared
 *
 * Public: No
 */
 
params ["_radioId"];

[_radioId, "getState", "radioShared"] call EFUNC(sys_data,dataEvent)
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Generates a list of actions for radios that are being shared by a unit.
 *
 * Arguments:
 * 0: Unit with a shared radio <OBJECT>
 *
 * Return Value:
 * Array of actions <ARRAY>
 *
 * Example:
 * [cursorTarget] call acre_sys_external_fnc_listChildrenActions
 *
 * Public: No
 */

params ["_target"];

private _actions = [];
private _sharedRadios = [_target] call FUNC(getSharedExternalRadios);

// Add external radios in order to be able to "give" them to other players
{
    _sharedRadios pushBackUnique _x;
} forEach ACRE_ACTIVE_EXTERNAL_RADIOS;

// Add player's radios that are shared
private _ownSharedRadios = [acre_player] call FUNC(getSharedExternalRadios);
{
    _sharedRadios pushBackUnique _x;
} forEach _ownSharedRadios;

{
    private _owner = "";
    if (_x in ACRE_ACTIVE_EXTERNAL_RADIOS) then {
        _owner = format [" (%1)", name ([_x] call FUNC(getExternalRadioOwner))];
    };

    if (_x in _ownSharedRadios) then {
        _owner = format [" (%1)", name acre_player];
    };

    private _baseRadio = [_x] call EFUNC(api,getBaseRadio);
    private _item = ConfigFile >> "CfgWeapons" >> _baseRadio;
    private _displayName = getText (_item >> "displayName") + _owner;
    private _currentChannel = [_x] call EFUNC(api,getRadioChannel);
    _displayName = format [localize ELSTRING(ace_interact,channelShort), _displayName, _currentChannel];
    private _picture = getText (_item >> "picture");

    if ([_x, acre_player] call FUNC(checkListChildrenActions)) then {
        private _action = [_x, _displayName, _picture, {}, {true}, {_this call FUNC(childrenActions)}, [_x]] call ace_interact_menu_fnc_createAction;
        _actions pushBack [_action, [], _target];
    };
} forEach _sharedRadios;

_actions
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Handles death of unit, primarily for handling local player death. External radios are returned to the original owner.
 *
 * Arguments:
 * 0: Unit <OBJECT>
 *
 * Return Value:
 * Handled <BOOL>
 *
 * Example:
 * [player] call acre_sys_external_fnc_onPlayerKilled
 *
 * Public: No
 */

params ["_unit"];

if (_unit == acre_player) then {
    // All external radios in use are now returned to the owner
    {
        private _owner = [_x] call FUNC(getExternalRadioOwner);
        [_x, _owner] call FUNC(stopUsingExternalRadio);
    } forEach ACRE_ACTIVE_EXTERNAL_RADIOS;
};

true
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Check if a given action is available for a specific radio external radio.
 *
 * Arguments:
 * 1: Unique radio ID <STRING>
 *
 * Return Value:
 * Action is available <BOOL>
 *
 * Example:
 * ["ACRE_PRC_343_ID_1"] call acre_sys_external_fnc_radioCheckChildrenActions
 *
 * Public: No
 */

params ["_radioId"];

if (_radioId in ACRE_ACTIVE_EXTERNAL_RADIOS) exitWith {false};

vehicle acre_player == acre_player
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Start using an external radio.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 * 1: End user <OBJECT>
 *
 * Return Value:
 * None
 *
 * Example:
 * ["ACRE_PRC343_ID_1", acre_player] call acre_sys_external_fnc_startUsingExternalRadio
 *
 * Public: No
 */

params ["_radioID", "_endUser"];

private _owner = [_radioId] call FUNC(getExternalRadioOwner);
private _baseRadio =  [_radioId] call EFUNC(api,getBaseRadio);
private _displayName = getText (ConfigFile >> "CfgWeapons" >> _baseRadio >> "displayName");

// Do not flag as being externally used if it is already so (action give)
if !([_radioId] call FUNC(isExternalRadioUsed)) then {
    [_radioId, "setState", ["radioUsedExternally", [true, _endUser]]] call EFUNC(sys_data,dataEvent);

    // Handle remote owner
    private _message = format [localize LSTRING(hintTakeOwner), _endUser, _displayName];
    [QGVAR(startUsingRadioLocal), [_message, _radioId], _owner] call CBA_fnc_targetEvent;
};

// Add the radio to the player
ACRE_ACTIVE_EXTERNAL_RADIOS pushBackUnique _radioId;

// Set it as active radio.
[_radioId] call EFUNC(api,setCurrentRadio);

[[ICON_RADIO_CALL], [format [localize LSTRING(hintTake), _displayName, name _owner]], true] call CBA_fnc_notify;
#include "script_component.hpp"
/*
 * Author: ACRE2Team
 * Stop using an external radio, either returning it to the owner or giving it to another player. If target
 * is skipped, a default action to return to the owner is taken.
 *
 * Arguments:
 * 0: Unique radio identity <STRING>
 * 1: New end user/original owner <OBJECT>
 *
 * Return Value:
 * None
 *
 * Example:
 * ["ACRE_PRC343_ID_1", cursorTarget] call acre_sys_external_fnc_stopUsingExternalRadio
 *
 * Public: No
 */

params ["_radioId", "_target"];

private _owner = [_radioId] call FUNC(getExternalRadioOwner);

ACRE_ACTIVE_EXTERNAL_RADIOS = ACRE_ACTIVE_EXTERNAL_RADIOS - [_radioId];
[_radioId] call EFUNC(sys_radio,stopUsingRadio);

private _baseRadio =  [_radioId] call EFUNC(api,getBaseRadio);
private _displayName = getText (ConfigFile >> "CfgWeapons" >> _baseRadio >> "displayName");
[[ICON_RADIO_CALL], [format [localize LSTRING(hintReturn), _displayName, name _owner]], true] call CBA_fnc_notify;

if (_target == _owner) then {
    // Handle remote owner
    private _message = format [localize LSTRING(hintReturnOwner), name ([_radioId] call FUNC(getExternalRadioUser)), _displayName];
    [QGVAR(stopUsingRadioLocal), [_message, _radioId], _owner] call CBA_fnc_targetEvent;

    // Give radio back to the owner
    [_radioId, "setState", ["radioUsedExternally", [false, objNull]]] call EFUNC(sys_data,dataEvent);
} else {
    // Show a hint to the actual owner that the radio was given to another player
    private _message = format [localize LSTRING(hintGiveOwner), name ([_radioId] call FUNC(getExternalRadioUser)), _displayName, name _target];
    [QGVAR(giveRadioLocal), [_message, _radioId], _owner] call CBA_fnc_targetEvent;

    // Give radio to another player
    [QGVAR(giveRadioAction), [_radioId, _target], _target] call CBA_fnc_targetEvent;
};
#define COMPONENT sys_external
#define COMPONENT_BEAUTIFIED External Radios
#include "\idi\acre\addons\main\script_mod.hpp"

// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

#ifdef DEBUG_ENABLED_SYS_EXTERNAL
    #define DEBUG_MODE_FULL
#endif

#ifdef DEBUG_SETTINGS_SYS_EXTERNAL
    #define DEBUG_SETTINGS DEBUG_SETTINGS_SYS_EXTERNAL
#endif

#include "\idi\acre\addons\main\script_macros.hpp"

#define EXTERNAL_RADIO_MAXDISTANCE 2.0
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACRE">
    <Package name="sys_external">
        <Key ID="STR_ACRE_sys_external_externalRadios">
            <English>Shared Radios</English>
            <Spanish>Radios compartidas</Spanish>
            <German>Geteilte Funkgeräte</German>
            <Japanese>無線機を共有</Japanese>
            <Russian>Общие рации</Russian>
            <Polish>Udostępnione radia</Polish>
            <Chinese>共用無線電</Chinese>
            <Chinesesimp>共用无线电</Chinesesimp>
            <Korean>무전기가 공유됨</Korean>
            <Portuguese>Rádios Compartilhados</Portuguese>
            <Italian>Radio Condivise</Italian>
            <French>Radios partagées</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_shareRadio">
            <English>Share</English>
            <Spanish>Compartir</Spanish>
            <German>Teilen</German>
            <Japanese>共有</Japanese>
            <Russian>Передать</Russian>
            <Polish>Udostępnij</Polish>
            <Chinese>共用</Chinese>
            <Chinesesimp>共用</Chinesesimp>
            <Korean>공유</Korean>
            <Portuguese>Compartilhar</Portuguese>
            <Italian>Condividi</Italian>
            <French>Partager</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_unshareRadio">
            <English>Unshare</English>
            <Spanish>No compartir</Spanish>
            <German>Nicht teilen</German>
            <Japanese>共有解除</Japanese>
            <Russian>Забрать</Russian>
            <Polish>Wył.</Polish>
            <Chinese>取消共用</Chinese>
            <Chinesesimp>取消共用</Chinesesimp>
            <Korean>공유 해제</Korean>
            <Portuguese>Descompartilhar</Portuguese>
            <Italian>Non condividere</Italian>
            <French>Ne plus partager</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_takeHandset">
            <English>Take Handset</English>
            <Japanese>ハンドセットを取る</Japanese>
            <Chinese>拿起聽筒</Chinese>
            <Chinesesimp>拿起听筒</Chinesesimp>
            <Korean>헤드셋 얻기</Korean>
            <Portuguese>Pegar Aparelho</Portuguese>
            <Polish>Weź słuchawkę</Polish>
            <Italian>Prendi cuffia</Italian>
            <Spanish>Coger transmisor</Spanish>
            <French>Prendre le combiné</French>
            <German>Handteil nehmen</German>
            <Russian>Взять трубку</Russian>
        </Key>
        <Key ID="STR_ACRE_sys_external_takeHeadset">
            <English>Take Headset</English>
            <Spanish>Coger auriculares</Spanish>
            <German>Kopfhörer nehmen</German>
            <Japanese>ヘッドセットを取る</Japanese>
            <Russian>Взять наушники</Russian>
            <Polish>Weź słuchawki</Polish>
            <Chinese>拿起耳機</Chinese>
            <Chinesesimp>拿起耳机</Chinesesimp>
            <Korean>헤드셋 얻기</Korean>
            <Portuguese>Pegar Fones</Portuguese>
            <Italian>Prendi cuffia</Italian>
            <French>Prendre le casque</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_returnHandset">
            <English>Return Handset</English>
            <Japanese>ハンドセットを戻す</Japanese>
            <Chinese>放回聽筒</Chinese>
            <Chinesesimp>放回听筒</Chinesesimp>
            <Korean>헤드셋 돌려놓기</Korean>
            <Portuguese>Retornar Aparelho</Portuguese>
            <Polish>Odłóż słuchawkę</Polish>
            <Italian>Restituisci cuffia</Italian>
            <Spanish>Devolver transmisor</Spanish>
            <French>Rendre le combiné</French>
            <German>Handteil zurückgeben</German>
            <Russian>Вернуть трубку</Russian>
        </Key>
        <Key ID="STR_ACRE_sys_external_returnHeadset">
            <English>Return Headset</English>
            <Spanish>Devolver auriculares</Spanish>
            <German>Kopfhörer zurückgeben</German>
            <Japanese>ヘッドセットを戻す</Japanese>
            <Russian>Вернуть наушники</Russian>
            <Polish>Odłóż słuchawki</Polish>
            <Chinese>放回耳機</Chinese>
            <Chinesesimp>放回耳机</Chinesesimp>
            <Korean>헤드셋 돌려놓기</Korean>
            <Portuguese>Retornar Fones</Portuguese>
            <Italian>Restituisci cuffia</Italian>
            <French>Rendre le casque</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_giveHandset">
            <English>Give Handset</English>
            <Japanese>ハンドセットを渡す</Japanese>
            <Chinese>給予聽筒</Chinese>
            <Chinesesimp>给予听筒</Chinesesimp>
            <Korean>헤드셋 주기</Korean>
            <Portuguese>Dar Aparelho</Portuguese>
            <Polish>Podaj słuchawkę</Polish>
            <Italian>Passa cuffie</Italian>
            <Spanish>Dar transmisor</Spanish>
            <French>Donner le combiné</French>
            <German>Handteil geben</German>
            <Russian>Дать трубку</Russian>
        </Key>
        <Key ID="STR_ACRE_sys_external_giveHeadset">
            <English>Give Headset</English>
            <Spanish>Dar auriculares</Spanish>
            <German>Kopfhörer geben</German>
            <Japanese>ヘッドセットを渡す</Japanese>
            <Russian>Дать наушники</Russian>
            <Polish>Podaj słuchawki</Polish>
            <Chinese>給予耳機</Chinese>
            <Chinesesimp>给予耳机</Chinesesimp>
            <Korean>헤드셋 주기</Korean>
            <Portuguese>Dar Fones</Portuguese>
            <Italian>Passa cuffie</Italian>
            <French>Donner le casque</French>
        </Key>
        <Key ID="STR_ACRE_sys_external_hintGiveOwner">
            <English>%1 gave your %2 to %3</English>
            <Japanese>%1 は %2 を %3 へ渡しました</Japanese>
            <Chinese>%1把你的%2交給%3</Chinese>
            <Chinesesimp>%1把你的%2交给%3</Chinesesimp>
            <Korean>%1은 %3에게 %2를 주었다</Korean>
            <Portuguese>%1 deu seu %2 para %3</Portuguese>
            <Polish>%1 podał twoje %2 do %3</Polish>
            <Italian>%1 ha dato il tuo %2 a %3</Italian>
            <Spanish>%1 ha dado tu %2 a %3</Spanish>
            <French>%1 a donné votre %2 à %3.</French>
            <German>%1 gab dein %2 an %3</German>
            <Russian>%1 передал вашу %2 %3</Russian>
        </Key>
        <Key ID="STR_ACRE_sys_external_hintReturn">
            <English>Stop using %1 from %2</English>
            <Japanese>%1 を %2 で使用停止する</Japanese>
            <Russian>Перестать использовать %1 из %2</Russian>
            <Polish>Przestałeś używać %1 od %2</Polish>
            <Chinese>停止使用%2的%1</Chinese>
            <Chinesesimp>停止使用%2的%1</Chinesesimp>
            <Korean>%2의 %1을 사용중지</Korean>
            <Portuguese>Para de usar %1 de %2</Portuguese>
            <Italian>Smetti di usare %1 da %2</Italian>
            <Spanish>Deja de usar %1 de %2</Spanish>
            <French>Arrêter d'utiliser %1 de %2</French>
            <German>%1 von %2 nicht länger benutzen</German>
        </Key>
        <Key ID="STR_ACRE_sys_external_hintReturnOwner">
            <English>%1 stopped using your %2</English>
            <Japanese>%1 は %2 を使用停止しました</Japanese>
            <Chinese>%1停止使用你的%2</Chinese>
            <Chinesesimp>%1停止使用你的%2</Chinesesimp>
            <Korean>%1가 %2의 사용을 중지함</Korean>
            <Portuguese>%1 parou de usar seu %2</Portuguese>
            <Polish>%1 przestał używać twojego %2</Polish>
            <Italian>%1 ha smesso di usare il tuo %2</Italian>
            <Spanish>%1 ha dejado de usar tu %2</Spanish>
            <French>%1 a arrêté d'utiliser votre %2.</French>
            <German>%1 hat aufgehört dein %2 zu nutzen</German>
            <Russian>%1 прекратил использовать вашу %2</Russian>
        </Key>
        <Key ID="STR_ACRE_sys_external_hintTake">
            <English>Start using %1 from %2</English>
            <Japanese>%1 を %2 から使用する</Japanese>
            <Russian>Начать использовать %1 из %2</Russian>
            <Polish>Używasz %1 od %2</Polish>
            <Chinese>開始使用%2的%1</Chinese>
            <Chinesesimp>开始使用%2的%1</Chinesesimp>
            <Korean>%2의 %1을 사용시작</Korean>
            <Portuguese>Começar a usar %1 de %2</Portuguese>
            <Italian>Inizia ad usare %1 da %2</Italian>
            <Spanish>Usa %1 de %2</Spanish>
            <French>Commencer à utiliser %1 de %2</French>
            <German>Beginne %1 von %2 zu nutzen</German>
        </Key>
        <Key ID="STR_ACRE_sys_external_hintTakeOwner">
            <English>%1 started using your %2</English>
            <Japanese>%1 は %2 を使い始めました</Japanese>
            <Chinese>%1開始使用你的%2</Chinese>
            <Chinesesimp>%1开始使用你的%2</Chinesesimp>
            <Korean>%1가 %2의 사용을 시작함</Korean>
            <Portuguese>%1 começou a usar seu %2</Portuguese>
            <Polish>%1 używa twojego %2</Polish>
            <Italian>%1 ha iniziato ad usare il tuo %2</Italian>
            <Spanish>%1 está usando tu %2</Spanish>
            <French>%1 a commencé à utiliser votre %2.</French>
            <German>%1 benutzt jetzt dein %2</German>
            <Russian>%1 начал использовать вашу %2</Russian>
        </Key>
    </Package>
</Project>
#include "script_component.hpp"

[FUNC(externalRadioPFH), 0.91, []] call CBA_fnc_addPerFrameHandler;

if (!hasInterface) exitWith {};

[QGVAR(startUsingRadioLocal), {
    params ["_message", "_radioId"];

    // Manpack radios can also be used by the owner if they are not rack radios
    if ([_radioId] call EFUNC(sys_radio,isManpackRadio) && ([_radioId] call EFUNC(sys_rack,getRackFromRadio) == "")) then {
        ACRE_EXTERNALLY_USED_MANPACK_RADIOS pushBackUnique _radioId;
    } else {
        // fnc_stopUsingRadio cannot be used here since radio is in player's inventory
        // If it is the active radio
        if (ACRE_ACTIVE_RADIO isEqualTo _radioId) then {
            // Otherwise cleanup
            if (ACRE_ACTIVE_RADIO == ACRE_BROADCASTING_RADIOID) then {
                // Simulate a key up event to end the current transmission
                [] call EFUNC(sys_core,handleMultiPttKeyPressUp);
            };
            // Switch active radio, but first reset it
            ACRE_ACTIVE_RADIO = "";
            ACRE_ACTIVE_RADIO = ([] call EFUNC(sys_data,getPlayerRadioList)) select 0;
        };
        ACRE_EXTERNALLY_USED_PERSONAL_RADIOS pushBackUnique _radioId;
    };

    [[ICON_RADIO_CALL], [_message]] call CBA_fnc_notify;
}] call CBA_fnc_addEventHandler;

[QGVAR(stopUsingRadioLocal), {
    params ["_message", "_radioId"];

    // Manpack radios can also be used by the owner if they are not rack radios
    if ([_radioId] call EFUNC(sys_radio,isManpackRadio) && ([_radioId] call EFUNC(sys_rack,getRackFromRadio) == "")) then {
        ACRE_EXTERNALLY_USED_MANPACK_RADIOS = ACRE_EXTERNALLY_USED_MANPACK_RADIOS - [_radioId];
    } else {
        ACRE_EXTERNALLY_USED_PERSONAL_RADIOS = ACRE_EXTERNALLY_USED_PERSONAL_RADIOS - [_radioId];
    };

    [[ICON_RADIO_CALL], [_message], true] call CBA_fnc_notify;
}] call CBA_fnc_addEventHandler;

[QGVAR(giveRadioLocal), {
    params ["_message"];
    [[ICON_RADIO_CALL], [_message], true] call CBA_fnc_notify;
}] call CBA_fnc_addEventHandler;

[QGVAR(giveRadioAction), {_this call FUNC(startUsingExternalRadio)}] call CBA_fnc_addEventHandler;
#include "script_component.hpp"

ADDON = false;

PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;

ADDON = true;
PREP(allowExternalUse);
PREP(externalRadioPFH);
PREP(getExternalRadioOwner);
PREP(getExternalRadioUser);
PREP(getExternalUseStatus);
PREP(getSharedExternalRadios);
PREP(initRadio);
PREP(isExternalRadioAvailable);
PREP(isExternalRadioUsed);
PREP(isRadioShared);
PREP(onPlayerKilled);
PREP(startUsingExternalRadio);
PREP(stopUsingExternalRadio);

// ACE interaction
PREP(checkListChildrenActions);
PREP(checkReturnGive);
PREP(childrenActions);
PREP(listChildrenActions);
PREP(radioCheckChildrenActions);
PREP(isExternalActionAvailable);
#include "script_component.hpp"

#include "XEH_PREP.hpp"
 ¶L'!F~M»c‹ÇOÇÖA¬n