Welcome, Guest! Login | Register

Adding Muting to your Scoreboard [Print this Article]
Posted by: imperio59
Date posted: Feb 17 2005
User Rating: N/A
Number of views: 6211
Number of comments: 5
Description: A Small tutorial that explains how to put in simple muting on your scoreboard.
Hi folks!
Before you start, this tutorial is based on omega's Scoreboard Article. You should follow through his tutorial before starting on this one, or have a functionning scoreboard.
This tutorial will do two things:
First, we will add a few lines to enable mouse input in your scoreboard when you hit the jump key!
Second, we will Set up a function to receive the "OnItemSelected" message from the m_pPlayerList element and we will put in the code to mute the selected player!

Okay, Let's get started!
First of all, we need to setup a new private variable in the Class's definition in clientscoreboarddialog.h like so:
 CODE (C++) 
private:
    int         m_iJumpKey;//Imperio59: Hold the id of the "jump" key!

This variable will hold the id of the key that the player has bound to "jump".
Next we need to go in the constructor and set the key's code to "KEY_NONE" (0) and we need to tell the game that we want to receive input for our Sectionned List:
 CODE (C++) 
CClientScoreBoardDialog::CClientScoreBoardDialog(IViewPort *pViewPort) : Frame( NULL, PANEL_SCOREBOARD )
{
m_iJumpKey = KEY_NONE;
...
m_pPlayerList = new SectionedListPanel(this, "PlayerList");
    m_pPlayerList->SetVerticalScrollbar(true);
    m_pPlayerList->SetMouseInputEnabled(true);
...
}

Now we need to add 2 lines at the top to get access to the gameuifuncs class:
 CODE (C++) 
#include "IGameUIFuncs.h" // for key bindings
extern IGameUIFuncs *gameuifuncs; // for key binding details


Next we go in the ShowPanel() function and actually set the variable to the right id, also we will tell the game to release the mouse once we close the panel:
 CODE (C++) 
void CClientScoreBoardDialog::ShowPanel(bool bShow)
{
...
if ( bShow )
    {
       
        if( m_iJumpKey == KEY_NONE ) // you need to lookup the jump key AFTER the engine has loaded
        {
            m_iJumpKey = gameuifuncs->GetVGUI2KeyCodeForBind( "jump" );
        }
...
    }
else
    {
        BaseClass::SetVisible( false );
        SetMouseInputEnabled( false );
               
    }
...
}

Now that our key id is all set, we need to create the function that will handle keyboard messages we get! Go back to the header file and put somewhere in a protected section the following declaration:
 CODE (C++) 
protected:
virtual void OnKeyCodePressed(vgui::KeyCode code);

And then we put the actual function somewhere at the bottom of ClientScoreBoardDialog.cpp:
 CODE (C++) 
void CClientScoreBoardDialog::OnKeyCodePressed(KeyCode code)
{
    if (m_iJumpKey != KEY_NONE && m_iJumpKey == code )
    {
        SetMouseInputEnabled(true);
    }
    else
    {
        BaseClass::OnKeyCodePressed( code );
    }
}


Ok, now you should be able to compile and run, bring up your scoreboard panel, hit your jump key and see the mouse, and you should also be able to click your own name.
Good! Now let's get to the muting part:
First we must declare our receiving function for the message in the header file, under a private section:
 CODE (C++) 
private:
MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", data );

Next under a protected section add the following:
 CODE (C++) 
protected:
    int FindPlayerIndexForItemID(int itemID);
    virtual void OnKeyCodePressed(vgui::KeyCode code);

Good! Now we're almost done. Next we'll actually implement the functions, put these at the bottom of ClientScoreBoardDialog.cpp:
 CODE (C++) 
//-----------------------------------------------------------------------------
// Purpose: Imperio59: returns the player index of the item ID
//-----------------------------------------------------------------------------
int CClientScoreBoardDialog::FindPlayerIndexForItemID(int itemID)
{
    if ( m_pPlayerList->IsItemIDValid(itemID) ) {
        KeyValues *kv = m_pPlayerList->GetItemData(itemID);
        kv = kv->FindKey(m_iPlayerIndexSymbol);
        if (kv)
            return kv->GetInt();
        return -1;
    }
    else {
        return -1;
    }
}
//-----------------------------------------------------------------------------
// Purpose: Imperio59: Intercept clicked panel messages so we can mute!
//-----------------------------------------------------------------------------
void CClientScoreBoardDialog::OnItemSelected(KeyValues * data)
{  
    int iRowId = data->GetInt("itemID");
    int playerIndex = FindPlayerIndexForItemID(iRowId);
    if (playerIndex == -1 )
        return;
    if ( GetClientVoiceMgr()->GetSpeakerStatus(playerIndex) != CVoiceStatus::VOICE_BANNED) {
        GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex,true);
    }
    else {
        GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex,false);
    }
}

Almost done! The last thing we must do is tell the SectionnedListPanel to send us messages, we do this in the constrctor like so:
 CODE (C++) 
m_pPlayerList->AddActionSignalTarget(this);//Imperio59: Listen for the list's messages, especially clicking so we can mute.


And that's it, now compile and run and it should let you mute players when you click on their names!

NOTE:If you have tried moving while the scoreboard is open you will have noticed you can't... This is simply a VGUI2 design flaw. If you SetKeyboardInputEnabled(true), you start capturing the keyboard events, and effectively trapping them. vgui2.dll seem to intercept them and tell the engine that it is fully handling it, i.e not to handle them. A possible solution would be looping back the event to the engine, but there doesn't seem to be a function to do it. Any sort of keyboard/mouse input handling requires enabling input for the VGUI2 element, wich prevents the engine from processing them. If someone finds a working way to loop back the messages to the engine, post it in the comment, for now the above code works but prevents moving while looking at the scoreboard. Enjoy :)

Rate This Article
This article has not yet been rated.

You have to register to rate this article.
User Comments Showing comments 1-5

Posted By: British_Bomber on Feb 16 2005 at 19:52:39
Very cool, not just for muting players but also getting to know how VGUI's handle input

Posted By: imperio59 on Feb 17 2005 at 03:42:30
Here's the actual reply from Valve's own Alfred Reynolds about the note at the end of the tutorial:
You can't have the scoreboard intercept keyboard events
(SetKeyBoardInputEnabled(false) must be set) if you want the engine to
process them ( which also means OnKeyCodePressed() won't be called as
the scoreboard won't get key presses).

- Alfred

Posted By: Unknown on Apr 05 2005 at 21:22:21
There are problems with using this method to hook bound keys and listen for them. Some of the numpad keycodes overlap with bound keys ( eg try binding jump to 'c' and notice that c doesn't work to trigger the mute, but numpad 3 does ).

I suggest grabbing the engine key code, which is a 1 to 1 mapping between commands and keys, and checking for that.

So instead of GetVgui2keycodeForBind, use:

m_iJumpKey = gameuifuncs->GetEngineKeyCodeForBind( "jump" );

Now the next problem is that OnKeyCodePressed passes vgui keys, and not engine keys. Here you should check what the last pressed engine key code was, like this:

void CYourVGUIPanel::OnKeyCodePressed(KeyCode code)
{
int lastPressedEngineKey = engine->GetLastPressedEngineKey();

if ( m_iJumpKey >= 0 && m_m_iJumpKey == lastPressedEngineKey )
{
// do the things you want to do when this is pressed
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}

There will be some examples of this in an upcoming official SDK.Edited by Unknown on Apr 05 2005, 21:23:29

Posted By: imperio59 on Jun 14 2005 at 17:50:13
Thanks, this looks indeed like a much better method :)

Posted By: ts2do on Jul 16 2005 at 02:59:50
for that last note, can't you just get the key's binding, then do engine->ClientCommand on that


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 (5 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!