Ingame menu for server plugins (CS:S only): Difference between revisions
m (Robot: fixing template case.) |
|||
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.''' | '''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.''' | ||
Revision as of 20:19, 19 January 2009

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 in-game menu is a usermessage so we will need to include src/tier1/bitbuf.cpp
into the project. This needs to be added to the project and then bitbuf.h needs to be included in 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.
Edit: This is not actually needed, valve have already got a function: engine->IndexOfEdict(edict_t *)
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())); No need what so ever of The Custom function Valve have there own engine->IndexOfEdict(pEntity); */ MRecipientFilter filter; filter.AddRecipient(engine->IndexOfEdict(pEntity)); bf_write *pBuffer = engine->UserMessageBegin( &filter, 10 ); 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 ); //true if there is more string yet to be received before displaying the menu, false otherwise 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.