Welcome, Guest! Login | Register

Creating a New VGUI Menu - Part 1 [Print this Article]
Posted by: rkzad
Date posted: Jun 09 2003
User Rating: 4.7 out of 5.0
Number of views: 10805
Number of comments: 2
Description: And getting it to show in your mod
Well I'm moving this tutorial over from Half-Life Coding Index to Wavelength since HLCI is hosted at Wavelength anyways, and HLCI is an index, not a tutorial. Feel free to PM/E-Mail me about any mistakes, but if you have any problems with VGUI please ask your questions on the Half-Life coding forum. I haven't touched Half-Life in about a year aside from updating my website, so I'm sure there are more qualified people who are willing to help on the forum.

Now, let me tell you exactly what we're gonna be doing today. First, we will create a very basic menu. Only a cancel button. Later on, we will add more buttons sending commands and doing all sorts of nifty things. So, because we are working with some VGUI, if you want to be able to actually try this out in your own code, make sure you have a compiler that will be able to code both the mp/hl.dll and the client.dll. One compiler that I am certain can do both, and is most recommended, is Microsoft Visual C++ 6 (MSVC). Next, make sure that you're liblist.gam has the following inside:
 CODE (liblist.gam) 
svonly "0"
cldll "1"

These are just some necessary things to make sure your mod will look for a client.dll also. It will search for this dll in "your_mod_folder/cl_dlls/client.dll", while it will look for your mp/hl.dll wherever you specified it in the "gamedll" parameter. Enough about liblist.gam though (there are some tutorials on this you can find elsewhere). Let's get coding!

Let's open up the mp/hl workspace, and open player.h. Insert this at line 74:
 CODE (C++) 
class CBasePlayer : public CBaseMonster
{
public:
    void    ShowVGUIMenu(int iMenuID); // VGUI Tutorial
    int random_seed;

There we go. This is a prototype for our function that will tell the client dll to show one of the VGUI menus.

Now, let's implement it. Open player.cpp and go to line 237:
 CODE (C++) 
LINK_ENTITY_TO_CLASS( player, CBasePlayer );

// Start - VGUI Tutorial
void CBasePlayer :: ShowVGUIMenu(int iMenuID)
{
    MESSAGE_BEGIN(MSG_ONE, gmsgVGUIMenu, NULL, pev);
        WRITE_BYTE( iMenuID );
    MESSAGE_END();
}
// End - VGUI Tutorial

void CBasePlayer :: Pain( void )

But, hold on a sec. Where did gmsgVGUIMenu come from? That's right! It's not declared. First let's go to line 190:
 CODE (C++) 
int gmsgShowMenu = 0;
int gmsgGeigerRange = 0;
int gmsgVGUIMenu = 0; // VGUI Tutorial

void LinkUserMessages( void )

Next, let's go to the end of that LinkUserMessages and add the following:
 CODE (C++) 
    gmsgFade = REG_USER_MSG("ScreenFade", sizeof(ScreenFade));
    gmsgAmmoX = REG_USER_MSG("AmmoX", 2);
    gmsgVGUIMenu = REG_USER_MSG("VGUIMenu", 1); // VGUI Tutorial
}

LINK_ENTITY_TO_CLASS( player, CBasePlayer );

The above is needed to tell the client dll what message we are sending in ShowVGUIMenu. Now that that's done, it's time to put our ShowVGUIMenu to use! Let's open client.cpp and go to line 380:
 CODE (C++) 
        GetClassPtr((CBasePlayer *)pev)->SelectLastItem();
    }
    // Start - VGUI Tutorial
    else if ( FStrEq(pcmd, "vguimenu" ) )
    {
        if (CMD_ARGC() >= 1)
            GetClassPtr((CBasePlayer *)pev)->ShowVGUIMenu(atoi(CMD_ARGV(1)));
    }
    // End - VGUI Tutorial
    else if ( g_pGameRules->ClientCommand( GetClassPtr((CBasePlayer *)pev), pcmd ) )

Now, we can use the command "vguimenu xx" to access any of the VGUI Menus we want! Build your mp.dll and put it in your mod's gamedll folder. Start a game of HL, and in the console type "vguimenu 5" (without the ") and something close to the following should show:

user posted image

So that menu may not look the best... but that's besides the point. That was a test to see whether or not our new vguimenu command works. Now, we will finally create our own new VGUI menu! Lets open up the cl_dll project now. Open up vgui_TeamFortressViewport.h at line 46:
 CODE (C++) 
class CClassMenuPanel;
class CTeamMenuPanel;
class CFirstMenu; // VGUI Tutorial

char* GetVGUITGAName(const char *pszName);

Now we have our class prototyped, just in case we need to reference to it before we wrote the next bit of text (goto line 1118):
 CODE (C++) 
public:
    CTFScrollPanel(int x,int y,int wide,int tall);
};

// Start - VGUI Tutorial
//================================================================
// First VGUI menu!
//============================================================
class CFirstMenu : public CMenuPanel
{
private:
    CommandButton       *m_pCancelButton;

public:
    CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall);
};
// End - VGUI Tutorial

//================================================================
// Menu Panels that take key input

There we go, we have our first menu class. Now let's implement our constructor. Add a new file to the Source Files of the cl_dll project named "vgui_FirstMenu.cpp". Open up that file and write in the following:
 CODE (C++) 
#include "hud.h"
#include "cl_util.h"
#include "vgui_TeamFortressViewport.h"


CFirstMenu :: CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
    m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "Cancel" ), 5, 5, XRES(75), YRES(30));
    m_pCancelButton->setParent( this );
    m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
}

Now, what this does, is create our cancel button with "Cancel" as the text on it, position it at x(5), y(5), and let it have a width of 75 and a height of 30. XRES and YRES make our numbers relative to either 640x480 or 320x240. The second line tells CFirstMenu that it now has a new child that it has to show, or hide, or do whatever it should to it's children. The last line makes it so that when you click on the button, it'll send a MenuHandler that will hide our menu. Next, we will make the necessary changes so that we may open our VGUI menu through our ShowVGUIMenu command. Goto line 278:
 CODE (C++) 
    void         CreateClassMenu( void );
    CMenuPanel*  ShowClassMenu( void );
    // Start - VGUI Tutorial
    void         CreateFirstMenu( void );
    CMenuPanel*  ShowFirstMenu( void );
    // End - VGUI Tutorial
    void         CreateSpectatorMenu( void );

The first function, later on, is what gets called early in the VGUI starting stage to create our menu. The second function gets called every time we want our FirstMenu to show up. Next, go to line 399 and add the following:
 CODE (C++) 
    CTeamMenuPanel  *m_pTeamMenu;
    CClassMenuPanel *m_pClassMenu;
    CFirstMenu      *m_pFirstMenu; // VGUI Tutorial
    ScorePanel      *m_pScoreBoard;

Now, our FirstMenu is part of the actual TeamFortressViewport class.

That's it for vgui_TeamFortressViewport.h! Now, open vgui_TeamFortressViewport.cpp! user posted image Let's take a look at line 468:
 CODE (C++) 
    m_pTeamMenu = NULL;
    m_pClassMenu = NULL;
    m_pFirstMenu = NULL; // VGUI Tutorial
    m_pScoreBoard = NULL;

These are necessary so that we don't get some wacko information in our menu. So we make it all NULL. Later on in this function we will create our menu. You can do that at line 532:
 CODE (C++) 
    // VGUI MENUS
    CreateTeamMenu();
    CreateClassMenu();
    CreateFirstMenu(); // VGUI Tutorial
    CreateScoreBoard();

Now, when the TeamFortressViewport is being constructed, our FirstMenu will be created! Let's continue on to line 553:
 CODE (C++) 
    // Force each menu to Initialize
    if (m_pTeamMenu)
    {
        m_pTeamMenu->Initialize();
    }
    if (m_pClassMenu)
    {
        m_pClassMenu->Initialize();
    }
    // Start - VGUI Tutorial
    if (m_pFirstMenu)
    {
        m_pFirstMenu->setVisible( false );
    }
    // End - VGUI Tutorial
    if (m_pScoreBoard)
    {
        m_pScoreBoard->Initialize();
        HideScoreBoard();
    }

This is necessary so that whenver a new map gets loaded, our menu will be hidden again. Now, let's make a quick little change in tf_defs.h (External Dependencies) at line 1132:
 CODE (C++) 
#define MENU_REFRESH_RATE           25

// VGUI Tutorial
#define MENU_FIRSTMENU              30

//============================
// Timer Types

Now, we have a defined number assigned to our FirstMenu! We may use this number when we use vguimenu (ex: "vguimenu 30").

Now, back to vgui_TeamFortressViewport.cpp, let's go all the way down to line 1506:
 CODE (C++) 
    case MENU_CLASS:
        pNewMenu = ShowClassMenu();
        break;

    // Start - VGUI Tutorial
    case MENU_FIRSTMENU:
        pNewMenu = ShowFirstMenu();
        break;
    // End - VGUI Tutorial

    default:
        break;
    }

Does the name of the function we're putting this in look familiar? Well it should if you were paying attention to all I've been saying for a long while now. No, this is not the same thing we had before. This is what the actual VGUI code is using to show our menus. See how it'll take the MenuID (in our case, 30), and then when it gets to case MENU_FIRSTMENU, since MenuID equals 30, it will show our FirstMenu, cool, huh?

Now then. We've made our ShowFirstMenu and CreateFirstMenu prototypes, and we've used the functions on several occasions in the code. But we still haven't implemented them! Let's go down to line 1618 and then add the following:
 CODE (C++) 
    m_pClassMenu->setParent(this);
    m_pClassMenu->setVisible( false );
}

// Start - VGUI Tutorial
//======================================================================================
// OUR FIRST MENU
//======================================================================================
// Show the FirstMenu
CMenuPanel* TeamFortressViewport::ShowFirstMenu()
{
    // Don't open menus in demo playback
    if ( gEngfuncs.pDemoAPI->IsPlayingback() )
        return NULL;

    m_pFirstMenu->Reset();
    return m_pFirstMenu;
}

void TeamFortressViewport::CreateFirstMenu()
{
    // Create the panel
    m_pFirstMenu = new CFirstMenu(100, false, 0, 0, ScreenWidth, ScreenHeight);
    m_pFirstMenu->setParent(this);
    m_pFirstMenu->setVisible( false );
}
// End - VGUI Tutorial

//======================================================================================
// SPECTATOR MENU

There we go! Now just compile your client.dll and move it to your mod's cl_dlls folder. Run Half-Life with your mod as your custom game, and start a game. In the console, type vguimenu 30 and, low and behold, the following pops up:

user posted image

Yeah, it's not much of a menu. But this tutorial has shown you how you can create your own. This is just the basic start! Check out part 2 for more fun with our menu.

Rate This Article
This article is currently rated: 4.7 out of 5.0 (3 Votes)

You have to register to rate this article.
Related Files
Zip FileFilename: pic1.gif
File Size: 32.3 KB
Zip FileFilename: pic2.gif
File Size: 36 KB

User Comments Showing comments 1-2

Posted By: morthy on Sep 04 2003 at 10:57:39
The word "WOW" comes to mind...

Posted By: InternetNightmare on Apr 30 2004 at 17:40:30
Very good tutorial! I like it :D


You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 05 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (7 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!