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.