Posted by: imperio59
Date posted: Feb 16 2005 User Rating: N/A | Number of views: 4932 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:
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:
| | | 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:
| | | #include "IGameUIFuncs.h" extern IGameUIFuncs *gameuifuncs; |
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:
| | | void CClientScoreBoardDialog::ShowPanel(bool bShow) { ... if ( bShow ) { if( m_iJumpKey == KEY_NONE ) { 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:
| | | protected: virtual void OnKeyCodePressed(vgui::KeyCode code); |
And then we put the actual function somewhere at the bottom of ClientScoreBoardDialog.cpp:
| | | 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:
| | | private: MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", data ); |
Next under a protected section add the following:
| | | 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:
| | |
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; } }
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:
| | | | m_pPlayerList->AddActionSignalTarget(this); |
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 :) |
|
User Comments
Showing comments 1-5
|
Very cool, not just for muting players but also getting to know how VGUI's handle input |
|
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 |
|
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, 15:23:29
|
|
|
Thanks, this looks indeed like a much better method :) |
|
|
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.
|
297 Approved Articless
6 Pending Articles
3940 Registered Members
0 People Online (10 guests)
|
|