Menus Step By Step (SourceMod Scripting)

From AlliedModders Wiki
Revision as of 09:38, 23 August 2012 by Powerlord (talk | contribs) (Safety save. Working on a new guide about writing menus by explaining them step by step.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The SourceMod Menu API is fairly useful for displaying an information panel, a menu, or a vote to users. This document talks specifically about menus and how to create one.

The working menu example

This is the working code example that we'll be talking about in the upcoming sections. If you need to, you can come back and look at it as you read the rest of this page.

We will be using PrintToServer to print text to the server console as we run through the events.

Usage of the Translations system is highly recommended and will be used in this example.

public OnPluginStart()
{
	LoadTranslations("menu_test.phrases");
	RegConsoleCmd("menu_test1", Menu_Test1);
}
 
public MenuHandler1(Handle:menu, MenuAction:action, param1, param2)
{
	switch(action)
	{
		case MenuAction_Start:
		{
			PrintToServer("Displaying menu");
		}
 
		case MenuAction_Display:
		{
			SetMenuTitle(menu, "%T", "Menu Title", param1);
			PrintToServer("Client %d was sent menu with panel %x", param1, param2);
		}
 
		case MenuAction_Select:
		{
			new String:info[32];
			GetMenuItem(menu, param2, info, sizeof(info));
			PrintToServer("Client %d selected %s", param1, info);
		}
 
		case MenuAction_Cancel:
		{
			PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2);
		}
 
		case MenuAction_End:
		{
			CloseHandle(menu);
		}
 
		case MenuAction_DrawItem:
		{
			new String:info[32];
			GetMenuItem(menu, param2, info, sizeof(info));
 
			if (param1 == 1 && StrEqual(info, "#choice3"))
			{
				return ITEMDRAW_DISABLED;
			}
		}
 
		case MenuAction_DisplayItem:
		{
			new String:info[32];
			GetMenuItem(menu, param2, info, sizeof(info));
			if (param1 == 1 && StrEqual(info, "#choice3"))
			{
				return RedrawMenuItem("Unselectable!");
			}
		}
	}
 
	return 0;
}
 
public Action:Menu_Test1(client, args)
{
	new Handle:menu = CreateMenu(MenuHandler1, MENU_ACTIONS_ALL);
	SetMenuTitle(menu, "%T", "Menu Title", LANG_SERVER);
	AddMenuItem(menu, "#choice1", "Choice 1");
	AddMenuItem(menu, "#choice2", "Choice 2");
	AddMenuItem(menu, "#choice3", "Choice 3");
	SetMenuExitButton(menu, false);
	DisplayMenu(menu, client, 20);
 
	return Plugin_Handled;
}

Step by Step

OnPluginStart

public OnPluginStart()
{
	RegConsoleCmd("menu_test1", Menu_Test1);
}

This block is here to register the command /menu_test1 so that this menu can be tested.

This block is beyond the scope of this page. See: Plugin Structure for OnPluginStart, Translations for LoadTranslations, and Commands for RegConsoleCmd.

Menu_Test1

Menu_Test1 is a ConCmd, which is beyond the scope of this page. See: Commands for more details on that. We're going to be talking about what's in it.

	new Handle:menu = CreateMenu(MenuHandler1, MENU_ACTIONS_ALL);

This creates a Handle


MenuHandler1

public MenuHandler1(Handle:menu, MenuAction:action, param1, param2)

MenuHandler1 is a function whose signature matches MenuHandler. It can be named something other than MenuHandler1. It must always be public and it will always have these arguments: Handle, MenuAction, cell, and cell in that order.

The Handle argument is always the menu that called the handler.

The two cell arguments meaning depend on the MenuAction argument.

The MenuAction argument is always one of 7 actions for a standard menu. They are: MenuAction_Start, MenuAction_Display, MenuAction_Select, MenuAction_Cancel, MenuAction_End, MenuAction_DrawItem, and MenuAction_DisplayIitem. We will discuss each of these as we reach their code.

MenuAction_Start

		case MenuAction_Start:
		{
			PrintToServer("Displaying menu");
		}

MenuAction_Start doesn't set param1 and param2. It is fired when the menu is displayed to one or more users using DisplayMenu, DisplayMenuAtItem, VoteMenu, or VoteMenuToAll.

MenuAction_Display

		case MenuAction_Display:
		{
			SetMenuTitle(menu, "Choose somethin', will ya?");
			PrintToServer("Client %d was sent menu with panel %x", param1, param2);
		}

MenuAction_Display is called once for each user a menu is displayed to. param1 is the client, param2 is the MenuPanel handle. You will likely never need the MenuPanel handle and it is beyond the scope of this page.

SetMenuTitle is used to change the menu's title based on the language of the user viewing it using the Translations system.

MenuAction_Select

		case MenuAction_Select:
		{
			decl String:info[32];
			GetMenuItem(menu, param2, info, sizeof(info));
			PrintToServer("Client %d selected %s", param1, info);
		}

MenuAction_Select is called when a user selects a non-control item on the menu (something added using AddMenuItem). param1 is the client, param2 is the menu position of the item the client selected.

Using the item position to check which item was selected is a bad idea, as item position is brittle and will break things if AddMenuItem or InsertMenuItem is used. It is recommended that you instead use the Menu item's info string.

GetMenuItem is used here to fetch the info string. Normally, an if/else if block would follow it.