Jump to content
Larrow

addAction menu system

Recommended Posts

Updated to Version 2.

Thought i would share an addAction menu system i wrote.
Your free to do with it what ever you desire, of course a little mention is always welcome. 😄

The actionMenu system provides a usable multi depth menu in the form of addActions. It has a simple structure of addAction parameters in the form of a multidimension array as seen below.

menu = [
	action,
	[
		//child menu
		action
	]
];

An action is the same as the full parameter list used in an Arma3 addAction command.
[title, script, arguments, priority, showWindow, hideOnUse, shortcut, condition]
See https://community.bistudio.com/wiki/addActionfor further details.
An actions code MUST be in the form of code {} not string.

For instance..

menu = [
	[ "Menu 0", {}, [], -1, false, false, "", "" ],
	[
		[ "Option 0", {hint "This is option 0 of sub menu 0"}, [], -1, false, false, "", "" ],
		[ "Option 1", {hint "This is option 1 of sub menu 0"}, [], -1, false, false, "", "" ]
	],
	[ "Menu 1", {}, [], -1, false, false, "", "" ],
	[
		[ "Option 0", {hint "This is option 0 of sub menu 1"}, [], -1, false, false, "", "" ],
		[ "Option 1", {hint "This is option 1 of sub menu 1"}, [], -1, false, false, "", "" ],
		[ "Menu 1-0", {}, [], -1, false, false, "", "" ],
		[
			[ "Option 0", {hint "This is option 0 of sub menu 1-0"}, [], -1, false, false, "", "" ],
			[ "Option 1", {hint "This is option 1 of sub menu 1-0"}, [], -1, false, false, "", "" ]
		]
	]
];
[ menu, player, false, 5, [ true, true, true, false ] ] call LARs_fnc_menuStart;

 
[ _menu,_vehicle, _shared, _menuDistance, _controls( HIDE, HOME, BACK, REMOVE ) ] call LARs_fnc_menuStart;

_menu - An array of actions to show, child menu actions follow their parent contained in an array - also supports as STRING the name of a global variable containing a menu structure so a _shared menu does not have to be passed over the network
 
_vehicle( optional ) - Object to apply menu to, defaults to player if not provided.
 
_shared( optional ) - Clients to also show menu for - follows BIS_fnc_MP convention ( bool, obj, side, client etc ) - ( default false ) if TRUE will pass to all clients, false does NOT pass to server but is used internally to not share. If _shared then menu is automatically added for JIP.
 
_menuDistance( optional ) - Default distance actions will be visible from, applied to ALL actions, overrides default 15m for non player actions ( default 5m )
 
_controls( optional ) - An array of booleans on whether to show the default menu navigation options ( default [ true, true, true, false ] )
The options being in order..

  • HIDE - Closes the actionMenu.
  • HOME - Returns menu to root. Only appears when you are deeper than one sub menu.
  • BACK - Returns you to the previous menu.
  • REMOVE - Closes the actionMenu and removes the menu from the vehicle, as such it is turned off by default.

To use simple copy the LARs folder from this test mission into yours and copy the CfgFunctions from the description.ext into yours.
If you already have a CfgFunctions just add my #include 'LARs\actionMenu.cpp'.

Further reading..

 


LARs_fnc_menuAddItem

[ _vehicle, _item, _depth, _pos, _isGlobal ] call LARs_fnc_menuAddItem;

_vehicle - Is the object holding the menu you want to change.

_item - Is a menu structure, can be one action or action plus submenu or a combination of multiples of these, also supports as STRING the name of a global variable containing a menu structure so a _shared item does not have to be passed over the network.

_depth( optional ) - Is an array of the path to current sub menu the item/s are to be added to, if not provided then the root menu is used. e.g [] would be the root menu, [ 1, 0 ] would be the first submenu (0) of the second submenu (1) of the root menu. Think of it like a breadcrumb.

_pos( optional ) - position in menu item will be inserted into, if not provided item will be added to the end of menu.

_isGlobal( optional ) - Same as BIS_fnc_MP options, menu will be passed and inserted into the menus of the provided targets.
 
Taking the menu example from above to add a new option into menu 1-0 inbetween option 0 and option 1 we would..


newMenu = [
    [ "Inseted Option", {hint "This option was inserted into Menu 1-0"}, [], -1, false, false, "", "" ]
];
[ player, newMenu, [ 1, 0 ], 1 ] call LARs_fnc_menuAddItem;

LARs_fnc_menuRemoveItem

[ _vehicle, _depth, _pos, _isGlobal ] call LARs_fnc_menuRemoveItem;

_vehicle - Is the object holding the menu you want to change.

_depth( optional ) - Is an array of the path to current sub menu the item/s are to be removed from, If not provided then root menu is used. e.g [] would be the root menu, [ 1, 0 ] would be the first submenu (0) of the second submenu (1) of the root menu. Think of it like a breadcrumb.

_pos( optional ) - position of item in menu to be removed, If the item has a child menu this will also be removed. If not provided then last menu item is removed.

_isGlobal( optional ) - Same as BIS_fnc_MP options, menu will be passed and removed from the menus of the provided targets.
 
Continuing with the menu example to remove the option we just inserted into menu 1-0 we would..

 


[ player, [ 1, 0 ], 1 ] call LARs_fnc_menuRemoveItem;

Other things to note..

  • Menus can be multidepth and there is no limit.
  • Each action should have a priority of -1 to make sure they ordered properly.
  • Instead of a bolean for hideOnUse you can also set it to -1, 0 or 1
    • false - leaves action menu open
    • true - closes action Menu
    • -1 - closes action menu and exits menu system
    • 0 - leaves action menu open and resets menu system
    • 1 - closes action menu and resets menu system
    • Otherwise everything else works as per an addAction

The color of the default actionMenu controls can be changed by using LARs_actionMenuColor = "#FFC403"; in your description.ext and replacing the hex number with your own.
http://www.colorpicker.com/is an easy place to find your color numbers.

 

You can set a default prefix that will be used for all menu items by setting LARs_actionMenuPrefix in your description.ext.

Some variables are available for mission designers to query that maybe of some help.
"LARs_remoteMenu" - Only available on a player that has their own active actionMenu but is currently viewing a menu from another object - returns the object else nil
"LARs_menuDepth" - current menu path being displayed
"LARs_menuSystemActive" - true if object has an active actionMenu else nil
"LARs_activeMenu" - The current active menu structure


This info can also be found in LARs\actionMenu\info.txt

Downloaded from : HERE


Any problems or suggestions just post and ill try to help.

  • Like 8
  • Thanks 4

Share this post


Link to post
Share on other sites

Thanks for sharing, might come in handy for future mission making

Share this post


Link to post
Share on other sites

I have some questions, which i hope you can help with. I used the addaction script. At the moment is like this

menu = [

    //TEST
    [ "<t color='#000000'>    PLAYER SUBMENU</t>", {}, "", -1, false, false, "", "" ],
    [
        //TEST 0
        [ "<t color='#000000'>    RANKED LOADOUTS</t>", {}, "", -1, false, false, "", "" ],
        [

            
			[ "<t color='#000000'>    CORPORAL</t>", { hint "CORPORAL LOADOUT" }, "", -1, false, true, "", "" ],
			[ "<t color='#000000'>    SERGEANT</t>", { hint "SERGEANT LOADOUT" }, "", -1, false, true, "", "" ],
			[ "<t color='#000000'>    LIEUTENANT</t>", { hint "LIEUTENANT LOADOUT" }, "", -1, false, true, "", "" ],
			[ "<t color='#000000'>    CAPTAIN</t>", { hint "CAPTAIN LOADOUT" }, "", -1, false, true, "", "" ],
			[ "<t color='#000000'>    MAJOR</t>", { hint "MAJOR LOADOUT" }, "", -1, false, true, "", "" ],
			[ "<t color='#000000'>    COLONEL</t>", { hint "COLONEL LOADOUT" }, "", -1, false, true, "", "" ]
			

        ]

        
    ]

];

I have made several loadouts that corresponding to the players level. The loadout script looks like this :

_unit = _this select 0;
// "Remove existing items";
removeAllWeapons _unit;
removeAllItems _unit;
removeAllAssignedItems _unit;
removeUniform _unit;
removeVest _unit;
removeBackpack _unit;
removeHeadgear _unit;
removeGoggles _unit;

// "Add containers";
_unit forceAddUniform "U_I_G_Story_Protagonist_F";
_unit addVest "V_PlateCarrier_Kerry";
_unit addBackpack "B_Carryall_mcamo";
_unit addItemToBackpack "FirstAidKit";
for "_i" from 1 to 5 do {_unit addItemToBackpack "30Rnd_65x39_caseless_mag";};
for "_i" from 1 to 5 do {_unit addItemToBackpack "11Rnd_45ACP_Mag";};
_unit addHeadgear "H_Watchcap_blk";
_unit addGoggles "G_Squares_Tinted";

// "Add weapons";
_unit addWeapon "arifle_MXM_Black_F";
_unit addPrimaryWeaponItem "muzzle_snds_H";
_unit addPrimaryWeaponItem "acc_flashlight";
_unit addPrimaryWeaponItem "optic_Nightstalker";
_unit addWeapon "hgun_Pistol_heavy_01_F";
_unit addHandgunItem "muzzle_snds_acp";
_unit addHandgunItem "optic_MRD";
_unit addWeapon "Binocular";

// "Add items";
_unit linkItem "ItemCompass";
_unit linkItem "ItemWatch";
_unit linkItem "ItemRadio";
_unit linkItem "ItemMap";


The player is getting their ranks based on a level they reach.

        if (_level == 4) then {
				player setRank "CORPORAL";
				
				_msg = format ["You've been promoted to the rank of %1.", rank player];
				["promoted",["\A3\Ui_f\data\GUI\Cfg\Ranks\corporal_gs.paa", _msg]] call BIS_fnc_showNotification;
				};

My question is how can i make the addactions mentioned above available only if a player reaches a specific rank ?. Is it possible to make the addaction available once the player reaches a specific rank and the player can use the addaction loadout every 600 secs?

 

Regards

 

Seed

Share this post


Link to post
Share on other sites

@Seed

I didn't read the whole script, but it should be:

[ "<t color='#000000'> CORPORAL</t>", { hint "CORPORAL LOADOUT" }, "", -1, false, true, "", "rank player == ""CORPORAL""" ],

more information:https://community.bistudio.com/wiki/addAction

 

And for the timer thing you should do a counter script, with is executed at the end of your loadout script.

Like this:

MYCOUNTER = 0;
WHILE {MYCOUNTER < 600} DO {MYCOUNTER = MYCOUNTER + 1;sleep 1;};

And then:

[ "<t color='#000000'> CORPORAL</t>", { hint "CORPORAL LOADOUT" }, "", -1, false, true, "", "rank player == ""CORPORAL"" && MYCOUNTER == 600" ],

Share this post


Link to post
Share on other sites

Hey Larrow, excellent thingie right there! Thanks a lot!

 

Could you possibly re-edit your OP to correct the formatting? That BIF update :D

Share this post


Link to post
Share on other sites

BIFF batman.gifaccomplished

Share this post


Link to post
Share on other sites

Hi 

This is GREAT!!! and works perfectly for what i am doing...

 

I have traders in my missions that the player can buy from and this submenu works well as i can categorize weapon types and so on.The addaction is linked to the traders so it is only available when you go near them however the menu is still available once activated no matter how far away you go unless you Xremove menu.

 

This will not work in my missions because players technically would only need to activate it at a trader once then as long as they do not press remove menu it will always be there and this breaks immersion.

 

SO.. is there a way to make it so that the menu exits on every child addaction.  So when the player buys a gun they will need to re activate the addaction to get back into it. My script below highlighted in red are the addaction i would need to exit the menu completely if selected. . Any help would be amazingggggg as  need this to work for my missions :) 

 

 
menu = [
 
    //TEST
    [ "<t color='#00FF3C'> Purchase</t>", {}, "", -1, false, false, "", "" ],
    [
        //TEST 0
        [ "<t color='#00FF3C'> Common Weapons</t>", {}, "", -1, false, false, "", "" ],
        [
 
            [ "<t color='#00FF3C'> Buy MX 6.5 mm $350</t>", "Buy\weapons\BuyMX 6.5 mm.sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy MXM 6.5 mm (Black) $550</t>", "Buy\weapons\BuyMXM 6.5 mm (Black).sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy Mk20 5.56 mm $600</t>", "Buy\weapons\BuyMk20 5.56 mm.sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy Vermin SMG .45 ACP $600</t>", "Buy\weapons\BuyVermin SMG .45 ACP.sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy Katiba 6.5 mm $800</t>", "Buy\weapons\BuyKatiba 6.5 mm.sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy Zafir 7.62 mm $800</t>", "Buy\weapons\BuyZafir 7.62 mm.sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy Mk20 5.56 mm (Camo) $800</t>", "Buy\weapons\BuyMk20 5.56 mm (Camo).sqf", "", -1, false, true, "", "" ],
            [ "<t color='#00FF3C'> Buy M320 LRR .408 $1200</t>", "Buy\weapons\BuyM320 LRR .408.sqf", "", -1, false, true, "", "" ],
            
             //TEST 0_1
            [ "<t color='#00FF3C'> Side Arms</t>", {}, "", -1, false, false, "", "" ],
            [
                [ "<t color='#00FF3C'> Buy ACP-C2 .45 $150</t>", "Buy\weapons\BuyACP-C2 .45.sqf", "", -1, false, true, "", "" ],
                [ "<t color='#00FF3C'> Buy Rook-40 9 mm $250</t>", "Buy\weapons\BuyRook-40 9 mm.sqf", "", -1, false, true, "", "" ],
                [ "<t color='#00FF3C'> Buy P07 9 mm $350</t>", "Buy\weapons\BuyP07 9 mm.sqf", "", -1, false, true, "", "" ],
                [ "<t color='#00FF3C'> Buy 4-five .45 $400</t>", "Buy\weapons\Buy4-five .45.sqf", "", -1, false, true, "", "" ],
                [ "<t color='#00FF3C'> Buy Zubr .45 $650</t>", "Buy\weapons\BuyZubr .45.sqf", "", -1, false, true, "", "" ]
                
            ]
        ],
        
        //TEST 1
        [ "<t color='#00FF3C'> Ranged and Explosives</t>", {}, "", -1, false, false, "", "" ],
        [
                  [ "<t color='#00FF3C'> RPG-42 Alamut $950</t>", "Buy\weapons\BuyRPG-42 Alamut.sqf", "", -1, false, true, "", "" ],
                  [ "<t color='#00FF3C'> Buy GM6 Lynx 12.7 mm $2300</t>", "Buy\weapons\BuyGM6 Lynx 12.7 mm.sqf", "", -1, false, true, "", "" ],
                  [ "<t color='#00FF3C'> Buy M320 LRR .408 $2000</t>", "Buy\weapons\BuyM320 LRR .408.sqf", "", -1, false, true, "", "" ],
                  [ "<t color='#00FF3C'> Buy x5 HandGrenade $600</t>", "Buy\weapons\BuyHandGrenade.sqf", "", -1, false, true, "", "" ],
                  [ "<t color='#00FF3C'> Buy x5 Smoke Grenade (White) $600</t>", "Buy\weapons\BuySmoke Grenade (White).sqf", "", -1, false, true, "", "" ]
 
        ],
        
        //TEST 2
        [ "<t color='#FF0000'> I don't have enough money</t>", {Hint"Better go get some then" }, "", -1, false, true, "", "" ]
 
 
 
 
    ]
       
    
  
];
 
//An action to start the menu, a menu can be started just by calling LARs_fnc_menuStart and passing it the menu array to display
Trader1 addAction [ "I have plenty of trade if you have money", { menu call LARs_fnc_menuStart }, [], 1, false, false, "", "isNil 'LARs_menuSystemActive'" ];
 
//***************
//Nothing worth editing below here
//*****************
 
LARs_fnc_menuUP = {
    LARs_menuDepth pushBack _this;
    call LARs_fnc_showMenu;
};
 
LARs_fnc_menuDOWN = {
    LARs_menuDepth deleteAt (( count LARs_menuDepth ) -1 );
    call LARs_fnc_showMenu;
};
 
LARs_fnc_showMenu = {
    call LARs_fnc_clearMenu;
    
    _stripActions = {
        _nextDepth = [];
        {
            if !( typeName ( _x select 0 ) isEqualTo typeName "" ) then {
                _nextDepth pushBack _x;
            };
        }forEach _this;
        _nextDepth
    };
    
    _addActionCode = {
        _code = _this;
        _actionCode = str ( _newAction select 1 );
        _actionCode = _actionCode select [ 1, ( count _actionCode ) - 2 ];
        _actionCode = compile format [ "%1; %2", _actionCode, _code ];
        _newAction set [ 1, _actionCode ];
    };
    
    _newMenu = +LARs_activeMenu;
    {
        _newmenu = _newMenu call _stripActions;
        _newMenu = _newMenu select _x;
    }forEach LARs_menuDepth;
    
    _childMenus = 0;
    {
        if ( typeName ( _x select 0 ) isEqualTo typeName "" ) then {
            _newAction = _x;
            
            //Do we have a child menu?
            if ( (( count _newMenu ) - 1 ) > _forEachIndex && { typeName (( _newMenu select ( _forEachIndex + 1 )) select 0 ) isEqualTo typeName [] } ) then {
                ( format [ "%1 call LARs_fnc_menuUP", _childMenus ] ) call _addActionCode;
            };
            
            //HideOnUse
            _hideOnUse = _newaction select 5;
            if ( typeName _hideOnUse isEqualTo typeName 0 ) then {
                switch ( _hideOnUse ) do {
                    case ( -1 ) : {
                        _newAction set [ 5, true ];
                        "call LARs_fnc_menuExit" call _addActionCode;
                    };
                    case ( 0 ) : {
                        _newAction set [ 5, false ];
                        "call LARs_fnc_menuReset" call _addActionCode;
                    };
                    case ( 1 ) : {
                        _newAction set [ 5, true ];
                        "call LARs_fnc_menuReset" call _addActionCode;
                    };
                };
            };
            
            _newAction = ( player addAction _newAction );
            LARs_currentActions pushBack _newAction;
        }else{
            _childMenus = _childMenus + 1;
        };
    }forEach _newMenu;
};
 
LARs_fnc_clearMenu = {
    //Remove current actions
    {
        player removeAction _x;
    }forEach LARs_currentActions;
    //Clear action array
    LARs_currentActions = [];
};
 
LARS_fnc_menuReset = {
    LARs_menuDepth = [];
    call LARs_fnc_showMenu;
};
 
LARs_fnc_menuStart = {
    //Default actions shown at every menu depth above 0
    LARs_defaultActions = [];
    {
        LARs_defaultActions pushBack ( player addAction _x );
    }forEach [
        //MENU HIDE - does nothing but hide actionMenu via true in the action
        ["[] MENU HIDE</t>", {}, "", -1, false, true, "", "!( isNil 'LARs_menuSystemActive' )"], //Always show if menu system is active
        //MENU HOME - Only show if we are deeper than 1 level
        [ "<img image='\A3\ui_f\data\gui\rsc\rscdisplayarcademap\icon_sidebar_hide_up.paa' size='0.7'' /> HOME</t>", { call LARs_fnc_menuReset }, "", -1, false, false, "", "count LARs_menuDepth > 1" ],
        //MENU BACK - Only show if we are deeper than base menu
        [ "<img image='\A3\ui_f\data\gui\rsc\rscdisplayarcademap\icon_sidebar_show.paa' size='0.7'' /> BACK</t>", { call LARs_fnc_menuDOWN }, "", -20, false, false, "", "count LARs_menuDepth > 0" ],
        //MENU EXIT
        ["<img image=\A3\ui_f\data\gui\rsc\rscdisplayarcademap\icon_exit_cross_ca.paa' size='0.7'' />I have changed my mind i'll come back later</t>", { call LARs_fnc_menuExit }, "", -20, false, false, "", "]
    ];
    
    LARs_currentActions = [];
    LARs_menuDepth = [];
    LARs_menuSystemActive = true;
    LARs_activeMenu = _this;
    call LARs_fnc_showMenu;
};
 
LARs_fnc_menuExit = {    
    call LARs_fnc_clearMenu;
    LARs_menuDepth = nil;
    LARs_currentActions = nil;
    LARs_activeMenu = nil;
    {
        player removeAction _x;
    }forEach LARs_defaultActions;
    LARs_defaultActions = nil;
    LARs_menuSystemActive = nil;
};
 

 

 

Share this post


Link to post
Share on other sites

Hi danleigh

Thanks for posting it reminded me that i had an updated version of this script sitting on my harddrive waiting to be uploaded.

The new version allows you to add menus to any object so this may well solve your issue as you can now put the menus on the traders rather than the player. This would also work out better for performance as the action will not be being evaluted every frame like they are when attached to a player.

You also would not need the start up action as the option would only become available when near a trader.

See first post for details and new download as i have changed it (only a little) to make it now a CfgFunctions based script.

Please let me know how you get on with it and post back if you experience an issues.

Larrow

Share this post


Link to post
Share on other sites

I needed a multi-level menu, did a google search, and found this old gem, which saved me a bunch of time! 😀 

 

Thanks Larrow!  I hope you are having fun where ever you are!

  • Like 3

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×