--- layout: wiki title: Interaction Menu Framework description: Explains how to add items to ACE's Interaction Menu. group: framework order: 0 parent: wiki mod: ace version: major: 3 minor: 0 patch: 0 --- ## 1. Types of actions - **External** (Type 0 / `ACE_Actions`) Something the user would do to an external object (eg. Tap another unit's shoulder) - **Self** (Type 1 / `ACE_SelfActions`) Something the user would do to themselves or to their vehicle (eg. Put in ear plugs / Check mounted Static Weapon's ammo) - **Zeus** (`ACE_ZeusActions`) Available to Zeus `ACE_Actions` and `ACE_SelfActions` can be added via config or by calling functions. Be aware that the functions modify the UI, and therefore need to be executed on client-side to take effect. The simplest action is just a condition and statement. The code to these are passed `[_target, _player, _actionParams]`. `_player` is `ace_player`; `_target` is the object being interacted with; and the 3rd argument is the optional action parameters (default `[]`). ## 2. Adding actions via config Example: ```cpp class CfgVehicles { class Man; class CAManBase: Man { class ACE_SelfActions { class danceParty { displayName = "dance"; condition = "[_player] call onDanceFloor"; exceptions[] = {}; statement = "_player switchMove 'TestDance'"; icon = "\z\dance.paa"; }; }; }; }; ``` | Config Name | Type | Description | | ---------- | ----------- | ------------------- | | `displayName` | String | Text shown to user | | `condition` | String (of code) | Condition to show the action | | `statement` | String (of code) | Statement run when selected | | `icon` | String (file path) | Icon shown (OPTIONAL) | | `exceptions` | Array (of strings) | Exceptions to `canInteractWith` conditions (e.g. `"notOnMap"`) (OPTIONAL) | | `insertChildren` | String (of code) | Code to return sub actions (OPTIONAL) | | `modifierFunction` | String (of code) | Code to modify this action (OPTIONAL) | | `runOnHover` | Number or String | (1=true) OR Condition code - Will run the statement on hover (OPTIONAL) | | `distance` | Number | External Base Actions Only, Max distance player can be from action point | | `position` | String (of code) | External Base Actions Only, Code to return a position in model cords (priority over `selection`) | | `selection` | String | External Base Actions Only, A memory point for `selectionPosition` | | `doNotCheckLOS` | Number | (1=true) - Ignores blocked LOS to the interaction node even when beyond 1.2m | | `showDisabled` | Number | Currently has no effect | | `enableInside` | Number | Currently has no effect | | `canCollapse` | Number | Currently has no effect | Actions can be inserted anywhere on the config tree, e.g. hearing's earplugs is a sub action of `ACE_Equipment`: ```cpp class CAManBase: Man { class ACE_SelfActions { class ACE_Equipment { class ACE_PutInEarplugs {}; }; }; }; ``` Interaction exceptions are defined by several components: | Component | Exception | Description | | ---------- | ----------- | ------------------- | | `captives` | `"isNotEscorting"` | Can interact while escorting a captive | | | `"isNotHandcuffed"` | Can interact while handcuffed | | | `"isNotSurrendering"` | Can interact while surrendering | | `common` | `"isNotDead"` | Can interact while dead | | | `"notOnMap"` | Can interact while in Map | | | `"isNotInside"` | Can interact while inside a vehicle | | | `"isNotInZeus"` | Can interact while in the zeus interface | | | `"isNotUnconscious"` | Can interact while unconscious | | `dragging` | `"isNotDragging"` | Can interact while dragging | | | `"isNotCarrying"` | Can interact while carrying | | `interaction` | `"isNotSwimming"` | Can interact while swimming/diving | | | `"isNotOnLadder"` | Can interact while climbing a ladder | | `refuel` | `"isNotRefueling"` | Can interact while carrying refueling nozzle | | `sitting` | `"isNotSitting"` | Can interact while sitting in a chair | ## 3. Adding actions via scripts Two steps, creating an action (array) and then adding it to either a class or object. Important: `ace_common_fnc_canInteractWith` is not automatically checked and needs to be explicitly called. ### 3.1 fnc_createAction `ace_interact_menu_fnc_createAction` ```sqf /* * Argument: * 0: Action name * 1: Name of the action shown in the menu * 2: Icon * 3: Statement * 4: Condition * 5: Insert children code (Optional) * 6: Action parameters (Optional) * 7: Position (Position array, Position code or Selection Name) , or (Optional) * 8: Distance (Optional) * 9: Other parameters [showDisabled,enableInside,canCollapse,runOnHover,doNotCheckLOS] (Optional) * 10: Modifier function (Optional) */ ``` ### 3.2 fnc_addActionToClass `ace_interact_menu_fnc_addActionToClass` ```sqf /* * Argument: * 0: TypeOf of the class * 1: Type of action, 0 for actions, 1 for self-actions * 2: Parent path of the new action * 3: Action * 4: Use Inheritance (Default: False) * 5: Classes excluded from inheritance (children included) (Default: []) */ ``` By default this function will not use inheritance, so actions will only be added to the specific class. ### 3.3 fnc_addActionToObject `ace_interact_menu_fnc_addActionToObject` ```sqf /* * Argument: * 0: Object the action should be assigned to * 1: Type of action, 0 for actions, 1 for self-actions * 2: Parent path of the new action (Example: `["ACE_SelfActions", "ACE_Equipment"]`) * 3: Action */ ``` ### 3.4 fnc_addActionToZeus `ace_interact_menu_fnc_addActionToZeus` ```sqf /* * Argument: * 0: Parent path of the new action (Example: `["ACE_ZeusActions"]`) * 1: Action */ ``` ### 3.5 Examples External: ```sqf _action = ["VulcanPinch","Vulcan Pinch","",{_target setDamage 1;},{true},{},[parameters], [0,0,0], 100] call ace_interact_menu_fnc_createAction; [cursorTarget, 0, ["ACE_TapShoulderRight"], _action] call ace_interact_menu_fnc_addActionToObject; ``` Self: ```sqf _condition = { (!pabst_radioFinder_on) && {(backpack _player) in pabst_radioFinder_backpacks} && {[_player, _target, []] call ace_common_fnc_canInteractWith} }; _statement = { [true] call pabst_fnc_radioFinder_action; }; _action = ["Open RDF","Radio Direction Finder","pabst\RDF.jpg",_statement,_condition] call ace_interact_menu_fnc_createAction; [(typeOf _unit), 1, ["ACE_SelfActions"], _action] call ace_interact_menu_fnc_addActionToClass; ``` Using `addActionToClass` inheritance: ```sqf // Adds action to check fuel levels for all land vehicles _action = ["CheckFuel", "Check Fuel", "", {hint format ["Fuel: %1", fuel _target]}, {true}] call ace_interact_menu_fnc_createAction; ["LandVehicle", 0, ["ACE_MainActions"], _action, true] call ace_interact_menu_fnc_addActionToClass; // Same as above, but children of "MRAP_01_Base" will not have the action _action = ["CheckFuel", "Check Fuel", "", {hint format ["Fuel: %1", fuel _target]}, {true}] call ace_interact_menu_fnc_createAction; ["LandVehicle", 0, ["ACE_MainActions"], _action, true, ["MRAP_01_Base"]] call ace_interact_menu_fnc_addActionToClass; // Adds action to check external fuel levels on tanks. Will be a sub action of the previous action. _action = ["CheckExtTank","Check External Tank","",{hint format ["Ext Tank: %1", 5]},{true}] call ace_interact_menu_fnc_createAction; ["Tank_F", 0, ["ACE_MainActions", "CheckFuel"], _action, true] call ace_interact_menu_fnc_addActionToClass; ``` Zeus: ```sqf _statement = { playSound3D ["alarm.ogg", theBase] }; _action = ["myMissionEvent1","Mission Event: Play Base Alarm","",_statement,{true}] call ace_interact_menu_fnc_createAction; [["ACE_ZeusActions"], _action] call ace_interact_menu_fnc_addActionToZeus; ``` ### 3.6 Advanced Example This adds an interaction to a unit that allows passing items that the player is carrying. - The child actions are generated dynamically based on the items in the player's inventory. - The parent action's display name is modified based on the item count. - When hovering on the action, a hint text is sent to the target. ```sqf _condition = { true }; _statement = { params ["_target", "_player", "_params"]; diag_log format ["_statement [%1, %2, %3]", _target, _player, _params]; // Run on hover: ["ace_common_displayTextStructured", ["someone is thinking of giving you items", 1.5, _target], [_target]] call CBA_fnc_targetEvent; }; _insertChildren = { params ["_target", "_player", "_params"]; diag_log format ["_insertChildren [%1, %2, %3]", _target, _player, _params]; // Add children to this action private _actions = []; { private _childStatement = {diag_log format ["givingItem %1", _this]; _target addItem (_this select 2);}; private _action = [format ["item:%1",_x], _x, "", _childStatement, {true}, {}, _x] call ace_interact_menu_fnc_createAction; _actions pushBack [_action, [], _target]; // New action, it's children, and the action's target } forEach (items _player); _actions }; _modifierFunc = { params ["_target", "_player", "_params", "_actionData"]; diag_log format ["_modifierFunc [%1, %2, %3]", _target, _player, _params]; // Modify the action - index 1 is the display name, 2 is the icon... _actionData set [1, format ["Give Items: %1", count (items player)]]; }; _action = ["GiveItems", "?","",_statement,_condition,_insertChildren,[123],"",4,[false, false, false, true, false], _modifierFunc] call ace_interact_menu_fnc_createAction; [q3, 0, ["ACE_MainActions"], _action] call ace_interact_menu_fnc_addActionToObject; ``` ### 3.7 Using `ace_interact_menu_newControllableObject` event CBA event `ace_interact_menu_newControllableObject` fires only once the first time the player controls a new object (new man, vehicle or controlled UAV) This is the ideal way to add self interaction actions, as adding them via `addActionToClass` will force self interaction actions to be compiled for classes that may never be used. ```sqf // Example: Add radio self-action to all civilian cars ["ace_interact_menu_newControllableObject", { params ["_type"]; // string of the object's classname if (!(_type isKindOf "Car")) exitWith {}; if ((getNumber (configFile >> "CfgVehicles" >> _type >> "side")) != 3) exitWith {}; private _action = ["playRadio","Play Radio","",{playMusic "NeverGonnaGiveYouUp"},{true}] call ace_interact_menu_fnc_createAction; [_type, 1, ["ACE_SelfActions"], _action, true] call ace_interact_menu_fnc_addActionToClass; }] call CBA_fnc_addEventHandler; ```