--- 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 ### 2.1 Class interactions 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 | ### 2.2 Vehicle interactions based on animations Some classes (usually vehicles) might have `AnimationSources` defined, which can hide/show e.g. spare wheels, ammo boxes, tools, doors etc. ACE offers a framework to be able to interact with those animations, which would allow players to e.g. remove the spare wheel from the vehicle, by hiding the spare wheel and spawning in a wheel object. {% raw %} ```cpp class Car_F; class Offroad_01_base_F: Car_F { class ace_interaction_anims { class HideBackpacks { // Class name of the animation (has to be defined in 'AnimationSources' of the class, with scope > 0) phase = 0; // The phase which is set after the action has successfully completed (default: 1) // At least 1 selection or position must be defined, otherwise an error will be raised and the interaction not added // Both selections[] and positions[] can be used at the same time selections[] = {"vhc_bags"}; // Selections where to have the interaction appear, equivalent to "_target selectionPosition 'vhc_bags'" if put in positions[] (default: []) positions[] = {{-1.15, -1.15, -0.2}, "_target selectionPosition ['vhc_bags', 'FireGeometry', 'AveragePoint']"}; // Positions where to have the interaction appear. It can either be model coordinates (in the array format) or a string containing code which returns model coordinates (default: []) items[] = {"B_TacticalPack_blk", "ACE_Wheel", "ACE_EntrenchingTool"}; // Items to spawn in when the progress bar finishes successfully (default: []) name = "$STR_a3_cfgvehicleclasses_backpacks0"; // Interaction name to display when interacting with the object (default: localised version of "Take it off") icon = "\A3\ui_f\data\igui\cfg\actions\take_ca.paa"; // Interaction icon to display when interacting with the object (default: "\A3\ui_f\data\igui\cfg\actions\take_ca.paa") text = "Removing backpacks..."; // Text to display in the progress bar (default: "") duration = 10; // Sets the progress bar duration (default: 10 seconds) distance = 2; // Sets at which distance the interactions can be accessed (default: 2) enabled = 1; // Enables (1) or disables (0) the interaction (default: 1) }; }; }; ``` {% endraw %} Individual animations can have the items they spawn in changed dynamically using a variable. If you set the items to `[]`, it will disable the interaction from completing (the progress bar will play, but once it reaches the end, it will stop and fail): ```sqf _target setVariable [format ["ace_interaction_animsItems_%1", _anim], ["B_TacticalPack_blk"], true]; // To disable the interaction from the example above _target setVariable ["ace_interaction_animsItems_HideBackpacks", [], true]; ``` ## 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; ```