Ingame menu for server plugins (CS:S only): Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (moved TOC)
mNo edit summary
Line 1: Line 1:
''' -- 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. Using the much simpler [http://developer.valvesoftware.com/wiki/Server_Plugins IServerPluginHelpers] interface is preferred.'''
{{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   *engine;
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) is 1
*(1<<0) enables 1
*(1<<1) is 2
*(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]]
Nextly : Colored Menu (Jeanlepail) :)

Revision as of 22:53, 14 March 2006

Broom icon.png
This article or section should be converted to third person to conform to wiki standards.

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.


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

#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;
}

Making the menu

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.

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

	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.