This tutorial should give you a deep understanding of the new AMXX menu system.
If you are having trouble following this tutorial, I suggest you read
Pawn Picture Tutorial.
Basic Menu - for interacting within a plugin or having a player select between objects ( such as a weapon menu )
Player Menu - for interacting with a selected player ( such as a kick menu )
Basic Vote Menu - for getting a preference from players ( such as a mapvote menu )
Sub-Menu - for having a menu within a menu ( such as a multilayered admin menu )
Advanced Vote Menu - for getting a more advanced preference ( such as a Galileo's map menu )
Multiple Menus with 1 Handler - for having multiple menus and only using a single menu_handler
Menu Items with Callbacks - for enabling/disabling menu items ( such as a Shop menu that disables items if you don't have enough money )
newmenus.inc - some helpful things from newmenus.inc
End Notes - some tips with the new menus
Basic Menu [top]
Code:
#include <amxmodx>
//..stuff for your plugin
"my_awesome_menu","AwesomeMenu" );
//note that we do not need to register the menu anymore, but just a way to get to it
}
//lets make the function that will make the menu
//first we need to make a variable that will hold the menu
"\rLook at this awesome Menu!:", "menu_handler" );
//Note - menu_create
//The first parameter is what the menu will be titled ( what is at the very top )
//The second parameter is the function that will deal/handle with the menu ( which key was pressed, and what to do )
//Now lets add some things to select from the menu
"\wI'm Selection #1", """\wI'm Selection #2", """\wI'm Secret Selection #3", ""//Note - menu_additem
//The first parameter is which menu we will be adding this item/selection to
//The second parameter is what text will appear on the menu ( Note that it is preceeded with a number of which item it is )
//The third parameter is data that we want to send with this item
//The fourth parameter is which admin flag we want to be able to access this item ( Refer to the admin flags from the amxconst.inc )
//The fifth parameter is the callback for enabling/disabling items, by default we will omit this and use no callback ( default value of -1 ) Refer to the Menu Items with Callbacks section for more information.
//Set a property on the menu
//Note - menu_setprop
//The first parameter is the menu to modify
//The second parameter is what to modify ( found in amxconst.inc )
//The third parameter is what to modify it to ( in this case, we are adding a option to the menu that will exit the menu. setting it to MEXIT_NEVER will disable this option )
//Additional note - MEXIT_ALL is the default property for MPROP_EXIT, so this is redundant
//Lets display the menu
//Note - menu_display
//The first parameter is which index to show it to ( you cannot show this to everyone at once )
//The second parameter is which menu to show them ( in this case, the one we just made )
//The third parameter is which page to start them on
}
//okay, we showed them the menu, now lets handle it ( looking back at menu_create, we are going to use that function )
//Because of the simplicity of this menu, we can switch for which item was pressed
//Note - this is zero-based, so the first item is 0
"Hooray! You selected the Awesome 1st Selection" );
//Note that if we dont want to continue through the function, we can't just end with a return. We want to kill the menu first
"OH NO! You selected the Awesome 2nd Selection! BEWARE!""You have selected the Awesome Admin Selection! Hail Teh Bail!""You exited the menu... what a bummer!" );
}
}
//lets finish up this function by destroying the menu with menu_destroy, and a return
Player Menu [top]
*Note - You should have an understanding of the
Basic Menu first.
Code:
#include <amxmodx>
#include <fun>
//Register a way to get to your menu...
"my_player_menu","AwesomeMenu"//Create a variable to hold the menu
"\rLook at this Player Menu!:", "menu_handler" );
//We will need to create some variables so we can loop through all the players
//Some variables to hold information about the players
//Fill players with available players
"a" ); // flag "a" because we are going to add health to players, but this is just for this specific case
//Start looping through all players
//Save a tempid so we do not re-index
tempid = players[i];
//Get the players name and userid as strings
//We will use the data parameter to send the userid, so we can identify which player was selected in the handler
"%d"//Add the item for this player
//We now have all players in the menu, lets display the menu
//Do a check to see if they exited because menu_item_getinfo ( see below ) will give an error if the item is MENU_EXIT
//now lets create some variables that will give us information about the menu and the item that was pressed/chosen
//heres the function that will give us that information ( since it doesnt magicaly appear )
//Get the userid of the player that was selected
//Try to retrieve player index from its userid
"k", userid ); // flag "k" : find player from userid
//If player == 0, this means that the player's userid cannot be found
//If the player is still alive ( we had retrieved alive players when formating the menu but some players may have died before id could select an item from the menu )
//Set their health to 100
Here is a generic player menu from ConnorMcLeod that you can use to easily add to your plugin
Code:
#include <amxmodx>
#include <amxmisc>
#define VERSION "0.0.1"
#define PLUGIN "Players Menu Generic"
"ConnorMcLeod""say /players", "ClCmd_Menu""Players Menu Misc", "PlayersMenuHandler""\y""h"'a''c'"%d""k""You have chosen #%s %s %s""Player %s<%s> seems to be disconnected"
Basic Vote Menu [top]
*Note - You should have an understanding of the
Basic Menu first.
Code:
#include <amxmodx>
//This will hold the VoteMenu
//This will hold the votes for each option
//This determines if a vote is already happening
//Register a way to get to your vote...
"start_vote","StartVote"//If there is already a vote, don't start another
"There is already a vote going." );
//We return PLUGIN_HANDLED so the person does not get Unknown Command in console
//Reset vote counts from any previous votes
gVotes[0] = gVotes[1] = 0;
//Note that if you have more than 2 options, it would be better to use the line below:
//arrayset( gVotes, 0, sizeof gVotes );
//Store the menu in the global
"\rLook at this Vote Menu!:", "menu_handler" );
//Add some vote options
"Vote Option 1", """Vote Option 2", "", 0 );
//We will need to create some variables so we can loop through all the players
//Fill players with available players
//Start looping through all players to show the vote to
//Save a tempid so we do not re-index
tempid = players[i];
//Show the vote to this player
//Increase how many players are voting
gVoting++;
}
//End the vote in 10 seconds
"EndVote"//If the menu was exited or if there is not a vote
//Note were not destroying the menu
//Increase the votes for what they selected
gVotes[ item ]++;
//Note were not destroying the menu
//If the first option recieved the most votes
"First option recieved most votes (%d )", gVotes[0] );
//Else if the second option recieved the most votes
"Second option recieved most votes (%d )", gVotes[1] );
//Otherwise the vote tied
"The vote tied at %d votes each.", gVotes[0] );
//Don't forget to destroy the menu now that we are completely done with it
//Reset that no players are voting
gVoting = 0;
}
Sub-Menu [top]
*Note - You should have an understanding of the
Basic Menu first.
Code:
#include <amxmodx>
"my_awesome_menu","AwesomeMenu""\rLook at this awesome Menu!:", "menu_handler""\wI'm Selection #1", """\wGo to SubMenu", """Hooray! You selected the Awesome 1st Selection"//Send them to the submenu
//Do nothing?
//Note that we will be using a different menu handler
"\rLook at this awesome Sub-Menu!:", "submenu_handler""\wI'm Sub-Selection #1", """\wI'm Sub-Selection #2", """Hooray! You selected the Awesome 1st Sub-Selection""OH NO! You selected the Awesome 2nd Sub-Selection! BEWARE!"//If they are still connected
//Lets send them back to the top menu
Advanced Vote Menu [top]
*Note - You should have an understanding of the
Basic Menu and the
Basic Vote Menu first.
Code:
#include <amxmisc>
#include <fun>
//How many different votes there will be in the menu
#define MAX_VOTEIDS 7
//How much "weight" a normal player's vote is worth
#define WEIGHT_PLAYER 1
//How much "weight" an admin's vote is worth
#define WEIGHT_ADMIN 2
//This will store the voteids
"start_vote","StartVote""There is already a vote going."//Reset vote counts from any previous votes
"\rWho should get 255 Health?", "menu_handler" );
//Here you can do whatever you want to add your voteids.
//We are going to use players for the example
"a" );
//Variable for if the player was added to the vote
//Loop through until we get enough voteids or run out of players
//Get a random player
//If they haven't been added yet
//We are setting the data to the voteid number
//Make sure we do not add them again
//Save the voteid as the user id for the player
//Go to the next voteid
voteid_count++;
}
}
//Now we have all the voteids
//Save a tempid so we do not re-index
tempid = players[i];
//Show the vote to this player
//Increase how many players are voting by their weight
"EndVote"//If the menu was exited or if there is not a vote
//Get the voteid number that was selected
//Increase the votes for what they selected by weight
//This will hold how many different votes were selected
//This will hold the top 3 votes
//This will hold the top 3 selected voteids
//Loop through all the voteids
//If the voteid recieved any votes
//If we are still trying to get the top 3
//Save the data for the current voteid selected
votes[votes_select] = gVotes[i];
voteid[votes_select] = i;
//Go to the next voteid that might have been selected
//Loop through all the top votes, replace any that are lower than the selected voteid
//If this one recieved less votes
//Change the data to the voteid with more votes
votes[j] = gVotes[i];
voteid[j] = i;
//Don't need to bother looking for more
//If noone voted
"CRICKEY! No one voted!" );
}
//Else if one voteid recieved all the votes
//Get the player id from the voteid
"k", voteid[0]);
VoteGiveHealth( player );
}
//Else if two different voteids recieved all the votes
//If they recieved even votes
//Give it to a random one
"Vote has tied. Choosing random from tied votes.""k"//Else if the first recieved the most
//Give it to the first
"k", voteid[ 0 ] );
VoteGiveHealth( player );
}
//Else the second recieved the most
//Give it to the second
"k", voteid[ 1 ] );
VoteGiveHealth( player );
}
}
//Else there were at least 3 different votes
//Here you might want to do run-off voting, but well just select a random one
"k""Could not determine a winner. Selecting random.""Look that Kangaroo %s has 255 Health!", szName );
}
}
Multiple Menus with 1 Handler [top]
*Note - You should have a good understanding of the
Sub Menu first.
Code:
#include <amxmodx>
"my_awesome_menu","AwesomeMenu""\rLook at this awesome Menu!:", "menu_handler" )
//Note that our data is 'm' to know it is from the main menu
"\wI'm Selection #1", "m""\wGo to SubMenu", "m""\rLook at this awesome Sub-Menu!:", "menu_handler" )
//Note that our data is 's' to know it is from the sub menu
"\wI'm Sub-Selection #1", "s""\wI'm Sub-Selection #2", "s"//Switch based on the first character of the data ( the 'm' or the 's')
//All our main menu data will be handled in this case
'm'"Hooray! You selected the Awesome 1st Selection"//All our sub menu data will be handled in this case
's'"Hooray! You selected the Awesome 1st Sub-Selection""OH NO! You selected the Awesome 2nd Sub-Selection! BEWARE!" );
}
}
//Note that this is still only for our sub menu
Menu Items with Callbacks [top]
*Note - You should have a good understanding of the
Player Menu first.
*Additional Note - This example uses a respawn function specific for Counter-Strike
Code:
#include <amxmodx>
#include <hamsandwich>
//Create a global variable to hold our callback
"my_player_menu","RespawnMenu" );
//Create our callback and save it to our variable
"menuitem_callback" );
//The first parameter is the public function to be called when a menu item is being shown.
"\rRevive Player Menu!:", "menu_handler""%d"//Add the item for this player with the callback
//Note that the last parameter that we usually omit is now filled with the callback variable
//This is our callback function. Return ITEM_ENABLED, ITEM_DISABLED, or ITEM_IGNORE.
//Create some variables to hold information about the menu item
//Get information about the menu item
//Note - item_callback should be equal to g_MenuCallback
//Get which player the item is for
"k", userid ); // flag "k" : find player from userid
//If the user is alive, we want to disable reviving them
//Otherwise we can just ignore the return value
//Note that returning ITEM_ENABLED will override the admin flag check from menu_additem
//Get the id of the player that was selected
"k", userid ); // flag "k" : find player from userid
//If the player is not alive
//Note - you should check this again in the handler function because the player could have been revived after the menu was shown
//Respawn them
newmenus.inc [top]
Code:
//The following defines are to be used with the native menu_setprop
#define MPROP_PERPAGE 1 /* Number of items per page ( param1 = number, 0=no paginating, 7=default ) */
#define MPROP_BACKNAME 2 /* Name of the back button ( param1 = string ) */
#define MPROP_NEXTNAME 3 /* Name of the next button ( param1 = string ) */
#define MPROP_EXITNAME 4 /* Name of the exit button ( param1 = string ) */
#define MPROP_TITLE 5 /* Menu title text ( param1 = string ) */
#define MPROP_EXIT 6 /* Exit functionality ( param1 = number, see MEXIT constants ) */
#define MPROP_NOCOLORS 8 /* Sets whether colors are not auto ( param1 = number, 0=default ) */
#define MPROP_NUMBER_COLOR 10 /* Color indicator to use for numbers ( param1 = string, "\r"=default ) */
//These two defines are to be used when changing a menu's MPROP_EXIT value
#define MEXIT_ALL 1 /* Menu will have an exit option ( default )*/
#define MEXIT_NEVER -1 /* Menu will not have an exit option */
//For more details about the following natives, check your actual newmenus.inc
""""
End Notes: [top]- Most of the menu_* natives will throw errors if they are passed an invalid menu. A menu is invalid if it is -1.
- You can expand on these in many ways, like only have one menu_handler to handle more than 1 menu
- If you are using a constant menu ( doesn't change at all ) you do not need to create and destroy it each time. It is better to save it as a global.
- These examples are not completely optimized, but they are for beginners and so they are simplified.
- List of Colors for menus: ( there are no other colors available )
- White - \w
- Yellow - \y
- Red - \r
- Grey/Disabled - \d
- To align text to the right - \R
- A menu will not show if it does not have any items.
- Text and blanks can only be added after an item.
- To hide a menu ( new or old style ) one can do:
Code:
show_menu( id, 0, "^n", 1 );
- One can remove the Next, Back, and Exit buttons to show up to 10 items by using:
Code:
menu_setprop( menu, MPROP_PERPAGE, 0 );
Anyway, Adios.