Ingame menu for server plugins (CS:S only): Difference between revisions
m (moved TOC) |
mNo edit summary |
||
Line 1: | Line 1: | ||
''' | {{TutPOV}} | ||
'''It should be noted, before you start, that this method is mod dependent and that this menu-system is not enabled in the standard SDK. This menu only seems to function in [[Counter-Strike: Source]]. Use of the simpler [[Server Plugins|IServerPluginHelpers]] interface is preferred.''' | |||
== Creating an in-game menu for server plugins == | == Creating an in-game menu for server plugins == | ||
The ingame menu is a usermessage so we will need to include bitbuf.cpp into the project. This can be found at src/tier1/bitbuf.cpp This needs to be added to the project and have | The ingame menu is a usermessage so we will need to include bitbuf.cpp into the project. This can be found at <code>src/tier1/bitbuf.cpp</code> This needs to be added to the project and have | ||
#include "bitbuf.h" | #include "bitbuf.h" | ||
in the includes at the top of serverplugin_empty.cpp | in the includes at the top of <code>serverplugin_empty.cpp</code> | ||
We will also need a Recipient Filter, you can use the one from mosca.br at [http://www.hl2coding.com HL2Coding] | We will also need a Recipient Filter, you can use the one from mosca.br at [http://www.hl2coding.com HL2Coding] | ||
===MRecipientFilter.cpp=== | ===MRecipientFilter.cpp=== | ||
<pre>#include "MRecipientFilter.h" | <pre> | ||
#include "MRecipientFilter.h" | |||
#include "interface.h" | #include "interface.h" | ||
#include "filesystem.h" | #include "filesystem.h" | ||
Line 25: | Line 27: | ||
#include "engine/IEngineSound.h" | #include "engine/IEngineSound.h" | ||
extern IVEngineServer | extern IVEngineServer *engine; | ||
extern IPlayerInfoManager *playerinfomanager; | extern IPlayerInfoManager *playerinfomanager; | ||
extern IServerPluginHelpers *helpers; | extern IServerPluginHelpers *helpers; | ||
// memdbgon must be the last include file in a .cpp file!!! | // memdbgon must be the last include file in a .cpp file!!! | ||
Line 112: | Line 114: | ||
}; | }; | ||
#endif</pre> | #endif | ||
</pre> | |||
===Usage=== | ===Usage=== | ||
These both need adding the project and have the line in the includes at the top or serverplugin_empty.cpp | These both need adding the project and have the line in the includes at the top or <code>serverplugin_empty.cpp</code> | ||
#include "MRecipientFilter.h" | #include "MRecipientFilter.h" | ||
We also need a function to get the clients index from their userid. | We also need a function to get the clients index from their userid. | ||
Line 159: | Line 162: | ||
The WriteShort contains a number of bits which tell the game which options are enabled for the menu. | The WriteShort contains a number of bits which tell the game which options are enabled for the menu. | ||
*(1<<0) | *(1<<0) enables 1 | ||
*(1<<1) | *(1<<1) enables 2 | ||
*etc.. | *etc.. | ||
To enable 4 and 7, one would use: | |||
(1<<3) | (1<<6) | |||
If you have done this correcly so far then you should have the menu show up in game when the client types a_menu. | If you have done this correcly so far then you should have the menu show up in game when the client types a_menu. | ||
== Making commands for the menu == | == Making commands for the menu == | ||
The menu run the command menuselect with the parameter as the option selected, so for this menu the commands would be menuselect 1, menuselect 2, and menuselect 3 | The menu run the command menuselect with the parameter as the option selected, so for this menu the commands would be <code>menuselect 1</code>, <code>menuselect 2</code>, and <code>menuselect 3</code> | ||
<pre> | <pre> | ||
Line 191: | Line 197: | ||
[[category:Tutorials]][[category:Programming]] | [[category:Tutorials]][[category:Programming]] | ||
Revision as of 22:53, 14 March 2006

It should be noted, before you start, that this method is mod dependent and that this menu-system is not enabled in the standard SDK. This menu only seems to function in Counter-Strike: Source. Use of the simpler IServerPluginHelpers interface is preferred.
The ingame menu is a usermessage so we will need to include bitbuf.cpp into the project. This can be found at src/tier1/bitbuf.cpp
This needs to be added to the project and have
#include "bitbuf.h"
in the includes at the top of serverplugin_empty.cpp
We will also need a Recipient Filter, you can use the one from mosca.br at HL2Coding
MRecipientFilter.cpp
#include "MRecipientFilter.h" #include "interface.h" #include "filesystem.h" #include "engine/iserverplugin.h" #include "dlls/iplayerinfo.h" #include "eiface.h" #include "igameevents.h" #include "convar.h" #include "Color.h" #include "shake.h" #include "IEffects.h" #include "engine/IEngineSound.h" extern IVEngineServer *engine; extern IPlayerInfoManager *playerinfomanager; extern IServerPluginHelpers *helpers; // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" MRecipientFilter::MRecipientFilter(void) { } MRecipientFilter::~MRecipientFilter(void) { } int MRecipientFilter::GetRecipientCount() const { return m_Recipients.Size(); } int MRecipientFilter::GetRecipientIndex(int slot) const { if ( slot < 0 || slot >= GetRecipientCount() ) return -1; return m_Recipients[ slot ]; } bool MRecipientFilter::IsInitMessage() const { return false; } bool MRecipientFilter::IsReliable() const { return false; } void MRecipientFilter::AddAllPlayers(int maxClients) { m_Recipients.RemoveAll(); for ( int i = 1; i <= maxClients; i++ ) { edict_t *pPlayer = engine->PEntityOfEntIndex(i); if ( !pPlayer || pPlayer->IsFree()) continue; //AddRecipient( pPlayer ); m_Recipients.AddToTail(i); } } void MRecipientFilter::AddRecipient( int iPlayer ) { // Already in list if ( m_Recipients.Find( iPlayer ) != m_Recipients.InvalidIndex() ) return; m_Recipients.AddToTail( iPlayer ); }
MRecipientFilter.h
#ifndef _MRECIPIENT_FILTER_H #define _MRECIPIENT_FILTER_H #include "irecipientfilter.h" #include "bitvec.h" #include "tier1/utlvector.h" class MRecipientFilter : public IRecipientFilter { public: MRecipientFilter(void); ~MRecipientFilter(void); virtual bool IsReliable( void ) const; virtual bool IsInitMessage( void ) const; virtual int GetRecipientCount( void ) const; virtual int GetRecipientIndex( int slot ) const; void AddAllPlayers( int maxClients ); void AddRecipient (int iPlayer ); private: bool m_bReliable; bool m_bInitMessage; CUtlVector< int > m_Recipients; }; #endif
Usage
These both need adding the project and have the line in the includes at the top or serverplugin_empty.cpp
#include "MRecipientFilter.h"
We also need a function to get the clients index from their userid.
int getIndexFromUserID(int userid) { edict_t *player; IPlayerInfo *info; for(int i = 1; i <= maxplayers; i++) //int maxplayers; has to be added after the includes and maxplayers=clientMax; in the ServerActivate function { player = engine->PEntityOfEntIndex(i); if(!player || player->IsFree() ) continue; info = playerinfomanager->GetPlayerInfo(player); if(info->GetUserID() == userid) return i; } return -1; }
I have used made the menu as a client command activated on the command a_menu.
if ( FStrEq( pcmd, "a_menu" ) ) { IPlayerInfo *playerInfo = playerinfomanager->GetPlayerInfo(pEntity); MRecipientFilter filter; filter.AddRecipient(getIndexFromUserID(playerInfo->GetUserID())); bf_write *pBuffer = engine->UserMessageBegin( &filter, 8 ); pBuffer->WriteShort( (1<<0) | (1<<1) | (1<<2) ); //Sets how many options the menu has pBuffer->WriteChar( -1 ); //Sets how long the menu stays open -1 for stay until option selected pBuffer->WriteByte( false ); pBuffer->WriteString( "1.Assault Rifle\n2.AWP\n3.Exit" ); //The text shown on the menu engine->MessageEnd(); return PLUGIN_STOP; }
This menu will be an alternative buy menu that will buy ammo, armor and grenades, as well as the primary weapon.
The WriteShort contains a number of bits which tell the game which options are enabled for the menu.
- (1<<0) enables 1
- (1<<1) enables 2
- etc..
To enable 4 and 7, one would use:
(1<<3) | (1<<6)
If you have done this correcly so far then you should have the menu show up in game when the client types a_menu.
The menu run the command menuselect with the parameter as the option selected, so for this menu the commands would be menuselect 1
, menuselect 2
, and menuselect 3
else if ( FStrEq( pcmd, "menuselect" ) ) { const char *parameter = engine->Cmd_Argv(1); switch(atoi(parameter)) { case 1: engine->ClientCommand (pEntity, "buy m4a1;buy ak47;buy primammo;buy vesthelm;buy deagle;buy secammo;buy flashbang;buy hegrenade;buy flashbang\n"); break; case 2: engine->ClientCommand (pEntity, "buy awp;buy primammo;buy vesthelm;buy deagle;buy secammo;buy flashbang;buy hegrenade;buy flashbang\n"); break; case 3: engine->ClientPrintf(pEntity, "Menu Exited"); break; } return PLUGIN_STOP; }
This will make the client run the commands to buy weapons ammo armor and grenades. The menu runs the commands.