1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 12:06:07 +08:00

Added most recent version of unmodified HL2 SDK for Orange Box engine

This commit is contained in:
Scott Ehlert
2008-09-15 01:07:45 -05:00
commit 055f5cd168
2907 changed files with 1271781 additions and 0 deletions

View File

@ -0,0 +1,386 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Basic BOT handling.
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "interface.h"
#include "filesystem.h"
#undef VECTOR_NO_SLOW_OPERATIONS
#include "mathlib/vector.h"
#include "eiface.h"
#include "edict.h"
#include "game/server/iplayerinfo.h"
#include "igameevents.h"
#include "convar.h"
#include "vstdlib/random.h"
#include "../../game/shared/in_buttons.h"
#include "../../game/shared/shareddefs.h"
//#include "../../game_shared/util_shared.h"
#include "engine/IEngineTrace.h"
extern IBotManager *botmanager;
extern IUniformRandomStream *randomStr;
extern IPlayerInfoManager *playerinfomanager;
extern IVEngineServer *engine;
extern IEngineTrace *enginetrace;
extern IPlayerInfoManager *playerinfomanager; // game dll interface to interact with players
extern IServerPluginHelpers *helpers; // special 3rd party plugin helpers from the engine
extern CGlobalVars *gpGlobals;
ConVar bot_forcefireweapon( "plugin_bot_forcefireweapon", "", 0, "Force bots with the specified weapon to fire." );
ConVar bot_forceattack2( "plugin_bot_forceattack2", "0", 0, "When firing, use attack2." );
ConVar bot_forceattackon( "plugin_bot_forceattackon", "0", 0, "When firing, don't tap fire, hold it down." );
ConVar bot_flipout( "plugin_bot_flipout", "0", 0, "When on, all bots fire their guns." );
ConVar bot_changeclass( "plugin_bot_changeclass", "0", 0, "Force all bots to change to the specified class." );
static ConVar bot_mimic( "plugin_bot_mimic", "0", 0, "Bot uses usercmd of player by index." );
static ConVar bot_mimic_yaw_offset( "plugin_bot_mimic_yaw_offset", "0", 0, "Offsets the bot yaw." );
ConVar bot_sendcmd( "plugin_bot_sendcmd", "", 0, "Forces bots to send the specified command." );
ConVar bot_crouch( "plugin_bot_crouch", "0", 0, "Bot crouches" );
// This is our bot class.
class CPluginBot
{
public:
CPluginBot() :
m_bBackwards(0),
m_flNextTurnTime(0),
m_bLastTurnToRight(0),
m_flNextStrafeTime(0),
m_flSideMove(0),
m_ForwardAngle(),
m_LastAngles()
{
}
bool m_bBackwards;
float m_flNextTurnTime;
bool m_bLastTurnToRight;
float m_flNextStrafeTime;
float m_flSideMove;
QAngle m_ForwardAngle;
QAngle m_LastAngles;
IBotController *m_BotInterface;
IPlayerInfo *m_PlayerInfo;
edict_t *m_BotEdict;
};
CUtlVector<CPluginBot> s_Bots;
void Bot_Think( CPluginBot *pBot );
// Handler for the "bot" command.
void BotAdd_f()
{
if ( !botmanager )
return;
static int s_BotNum = 0;
char botName[64];
Q_snprintf( botName, sizeof(botName), "Bot_%i", s_BotNum );
s_BotNum++;
edict_t *botEdict = botmanager->CreateBot( botName );
if ( botEdict )
{
int botIndex = s_Bots.AddToTail();
CPluginBot & bot = s_Bots[ botIndex ];
bot.m_BotInterface = botmanager->GetBotController( botEdict );
bot.m_PlayerInfo = playerinfomanager->GetPlayerInfo( botEdict );
bot.m_BotEdict = botEdict;
Assert( bot.m_BotInterface );
}
}
ConCommand cc_Bot( "plugin_bot_add", BotAdd_f, "Add a bot." );
//-----------------------------------------------------------------------------
// Purpose: Run through all the Bots in the game and let them think.
//-----------------------------------------------------------------------------
void Bot_RunAll( void )
{
if ( !botmanager )
return;
for ( int i = 0; i < s_Bots.Count(); i++ )
{
CPluginBot & bot = s_Bots[i];
if ( bot.m_BotEdict->IsFree() || !bot.m_BotEdict->GetUnknown()|| !bot.m_PlayerInfo->IsConnected() )
{
s_Bots.Remove(i);
--i;
}
else
{
Bot_Think( &bot );
}
}
}
bool Bot_RunMimicCommand( CBotCmd& cmd )
{
if ( bot_mimic.GetInt() <= 0 )
return false;
if ( bot_mimic.GetInt() > gpGlobals->maxClients )
return false;
IPlayerInfo *playerInfo = playerinfomanager->GetPlayerInfo( engine->PEntityOfEntIndex( bot_mimic.GetInt() ) );
if ( !playerInfo )
return false;
cmd = playerInfo->GetLastUserCommand();
cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat();
if( bot_crouch.GetInt() )
cmd.buttons |= IN_DUCK;
return true;
}
void Bot_UpdateStrafing( CPluginBot *pBot, CBotCmd &cmd )
{
if ( gpGlobals->curtime >= pBot->m_flNextStrafeTime )
{
pBot->m_flNextStrafeTime = gpGlobals->curtime + 1.0f;
if ( randomStr->RandomInt( 0, 5 ) == 0 )
{
pBot->m_flSideMove = -600.0f + 1200.0f * randomStr->RandomFloat( 0, 2 );
}
else
{
pBot->m_flSideMove = 0;
}
cmd.sidemove = pBot->m_flSideMove;
if ( randomStr->RandomInt( 0, 20 ) == 0 )
{
pBot->m_bBackwards = true;
}
else
{
pBot->m_bBackwards = false;
}
}
}
void Bot_UpdateDirection( CPluginBot *pBot )
{
float angledelta = 15.0;
int maxtries = (int)360.0/angledelta;
if ( pBot->m_bLastTurnToRight )
{
angledelta = -angledelta;
}
QAngle angle( pBot->m_BotInterface->GetLocalAngles() );
trace_t trace;
Vector vecSrc, vecEnd, forward;
while ( --maxtries >= 0 )
{
AngleVectors( angle, &forward );
vecSrc = pBot->m_BotInterface->GetLocalOrigin() + Vector( 0, 0, 36 );
vecEnd = vecSrc + forward * 10;
Ray_t ray;
ray.Init( vecSrc, vecEnd, Vector(-16, -16, 0 ), Vector( 16, 16, 72 ) );
CTraceFilterWorldAndPropsOnly traceFilter;
enginetrace->TraceRay( ray, MASK_PLAYERSOLID, &traceFilter, &trace );
if ( trace.fraction == 1.0 )
{
if ( gpGlobals->curtime < pBot->m_flNextTurnTime )
{
break;
}
}
angle.y += angledelta;
if ( angle.y > 180 )
angle.y -= 360;
else if ( angle.y < -180 )
angle.y += 360;
pBot->m_flNextTurnTime = gpGlobals->curtime + 2.0;
pBot->m_bLastTurnToRight = randomStr->RandomInt( 0, 1 ) == 0 ? true : false;
pBot->m_ForwardAngle = angle;
pBot->m_LastAngles = angle;
}
pBot->m_BotInterface->SetLocalAngles( angle );
}
void Bot_FlipOut( CPluginBot *pBot, CBotCmd &cmd )
{
if ( bot_flipout.GetInt() > 0 && !pBot->m_PlayerInfo->IsDead() )
{
if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
{
cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
}
if ( bot_flipout.GetInt() >= 2 )
{
QAngle angOffset = RandomAngle( -1, 1 );
pBot->m_LastAngles += angOffset;
for ( int i = 0 ; i < 2; i++ )
{
if ( fabs( pBot->m_LastAngles[ i ] - pBot->m_ForwardAngle[ i ] ) > 15.0f )
{
if ( pBot->m_LastAngles[ i ] > pBot->m_ForwardAngle[ i ] )
{
pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] + 15;
}
else
{
pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] - 15;
}
}
}
pBot->m_LastAngles[ 2 ] = 0;
pBot->m_BotInterface->SetLocalAngles( pBot->m_LastAngles );
}
}
}
void Bot_HandleSendCmd( CPluginBot *pBot )
{
if ( strlen( bot_sendcmd.GetString() ) > 0 )
{
//send the cmd from this bot
helpers->ClientCommand( pBot->m_BotEdict, bot_sendcmd.GetString() );
bot_sendcmd.SetValue("");
}
}
// If bots are being forced to fire a weapon, see if I have it
void Bot_ForceFireWeapon( CPluginBot *pBot, CBotCmd &cmd )
{
if ( Q_strlen( bot_forcefireweapon.GetString() ) > 0 )
{
pBot->m_BotInterface->SetActiveWeapon( bot_forcefireweapon.GetString() );
bot_forcefireweapon.SetValue( "" );
// Start firing
// Some weapons require releases, so randomise firing
if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
{
cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
}
}
}
void Bot_SetForwardMovement( CPluginBot *pBot, CBotCmd &cmd )
{
if ( !pBot->m_BotInterface->IsEFlagSet(EFL_BOT_FROZEN) )
{
if ( pBot->m_PlayerInfo->GetHealth() == 100 )
{
cmd.forwardmove = 600 * ( pBot->m_bBackwards ? -1 : 1 );
if ( pBot->m_flSideMove != 0.0f )
{
cmd.forwardmove *= randomStr->RandomFloat( 0.1, 1.0f );
}
}
else
{
// Stop when shot
cmd.forwardmove = 0;
}
}
}
void Bot_HandleRespawn( CPluginBot *pBot, CBotCmd &cmd )
{
// Wait for Reinforcement wave
if ( pBot->m_PlayerInfo->IsDead() )
{
if ( pBot->m_PlayerInfo->GetTeamIndex() == 0 )
{
helpers->ClientCommand( pBot->m_BotEdict, "joingame" );
helpers->ClientCommand( pBot->m_BotEdict, "jointeam 3" );
helpers->ClientCommand( pBot->m_BotEdict, "joinclass 0" );
}
}
}
//-----------------------------------------------------------------------------
// Run this Bot's AI for one frame.
//-----------------------------------------------------------------------------
void Bot_Think( CPluginBot *pBot )
{
CBotCmd cmd;
Q_memset( &cmd, 0, sizeof( cmd ) );
// Finally, override all this stuff if the bot is being forced to mimic a player.
if ( !Bot_RunMimicCommand( cmd ) )
{
cmd.sidemove = pBot->m_flSideMove;
if ( !pBot->m_PlayerInfo->IsDead() )
{
Bot_SetForwardMovement( pBot, cmd );
// Only turn if I haven't been hurt
if ( !pBot->m_BotInterface->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_PlayerInfo->GetHealth() == 100 )
{
Bot_UpdateDirection( pBot );
Bot_UpdateStrafing( pBot, cmd );
}
// Handle console settings.
Bot_ForceFireWeapon( pBot, cmd );
Bot_HandleSendCmd( pBot );
}
else
{
Bot_HandleRespawn( pBot, cmd );
}
Bot_FlipOut( pBot, cmd );
// Fix up the m_fEffects flags
pBot->m_BotInterface->PostClientMessagesSent();
cmd.viewangles = pBot->m_BotInterface->GetLocalAngles();
cmd.upmove = 0;
cmd.impulse = 0;
}
pBot->m_BotInterface->RunPlayerMove( &cmd );
}

View File

@ -0,0 +1,393 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="Serverplugin_empty"
ProjectGUID="{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
ExcludedFromBuild="false"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\common;..\..\public;..\..\public\tier0;..\..\public\tier1,..\..\game\server,..\..\game\shared"
PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;serverplugin_emptyONLY;_MBCS"
StringPooling="true"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
BufferSecurityCheck="false"
FloatingPointModel="2"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
GenerateXMLDocumentationFiles="false"
BrowseInformation="0"
BrowseInformationFile="$(IntDir)/"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="2"
ErrorReporting="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="false"
/>
<Tool
Name="VCLinkerTool"
UseUnicodeResponseFiles="false"
AdditionalDependencies="odbc32.lib odbccp32.lib"
ShowProgress="0"
OutputFile="$(OutDir)/serverplugin_empty.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\common;..\..\lib\public"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc;libcd;libcmt"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)/$(TargetName).pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)/$(TargetName).map"
SubSystem="2"
BaseAddress=" "
TargetMachine="1"
ErrorReporting="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCXDCMakeTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)/serverplugin_empty.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description=""
CommandLine=""
ExcludedFromBuild="false"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
ExcludedFromBuild="false"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..\..\common;..\..\public;..\..\public\tier0;..\..\public\tier1,..\..\game\server,..\..\game\shared"
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;serverplugin_emptyONLY;_MBCS"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)/"
ObjectFile="$(IntDir)/"
ProgramDataBaseFileName="$(IntDir)/"
GenerateXMLDocumentationFiles="false"
BrowseInformation="0"
BrowseInformationFile="$(IntDir)/"
WarningLevel="4"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
CompileAs="2"
ErrorReporting="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="false"
/>
<Tool
Name="VCLinkerTool"
UseUnicodeResponseFiles="false"
AdditionalDependencies="odbc32.lib odbccp32.lib"
ShowProgress="0"
OutputFile="$(OutDir)/serverplugin_empty.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\lib\common;..\..\lib\public"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc;libcd;libcmtd"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)/$(TargetName).pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)/$(TargetName).map"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
BaseAddress=" "
TargetMachine="1"
ErrorReporting="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCXDCMakeTool"
SuppressStartupBanner="true"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile="$(OutDir)/serverplugin_empty.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description=""
CommandLine=""
ExcludedFromBuild="false"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
>
<File
RelativePath="..\..\public\tier0\memoverride.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\serverplugin_bot.cpp"
>
</File>
<File
RelativePath=".\serverplugin_empty.cpp"
>
</File>
</Filter>
<Filter
Name="Link Libraries"
>
<File
RelativePath="..\..\lib\public\mathlib.lib"
>
</File>
<File
RelativePath="..\..\lib\public\tier0.lib"
>
</File>
<File
RelativePath="..\..\lib\public\tier1.lib"
>
</File>
<File
RelativePath="..\..\lib\public\tier2.lib"
>
</File>
<File
RelativePath="..\..\lib\public\vstdlib.lib"
>
</File>
</Filter>
<Filter
Name="Header Files"
>
<File
RelativePath="..\..\public\tier0\basetypes.h"
>
</File>
<File
RelativePath="..\..\public\Color.h"
>
</File>
<File
RelativePath="..\..\public\tier0\dbg.h"
>
</File>
<File
RelativePath="..\..\public\eiface.h"
>
</File>
<File
RelativePath="..\..\public\filesystem.h"
>
</File>
<File
RelativePath="..\..\public\vstdlib\ICommandLine.h"
>
</File>
<File
RelativePath="..\..\public\igameevents.h"
>
</File>
<File
RelativePath="..\..\public\tier1\interface.h"
>
</File>
<File
RelativePath="..\..\public\game\server\iplayerinfo.h"
>
</File>
<File
RelativePath="..\..\public\engine\iserverplugin.h"
>
</File>
<File
RelativePath="..\..\public\tier1\KeyValues.h"
>
</File>
<File
RelativePath="..\..\public\tier0\mem.h"
>
</File>
<File
RelativePath="..\..\public\tier0\memalloc.h"
>
</File>
<File
RelativePath="..\..\public\tier0\memdbgon.h"
>
</File>
<File
RelativePath="..\..\public\vstdlib\strtools.h"
>
</File>
<File
RelativePath="..\..\public\tier1\utlbuffer.h"
>
</File>
<File
RelativePath="..\..\public\tier1\utlmemory.h"
>
</File>
<File
RelativePath="..\..\public\tier1\utlvector.h"
>
</File>
<File
RelativePath="..\..\public\vstdlib\vstdlib.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,429 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include <stdio.h>
#include "interface.h"
#include "filesystem.h"
#include "engine/iserverplugin.h"
#include "game/server/iplayerinfo.h"
#include "eiface.h"
#include "igameevents.h"
#include "convar.h"
#include "Color.h"
#include "vstdlib/random.h"
#include "engine/IEngineTrace.h"
#include "tier2/tier2.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Interfaces from the engine
IVEngineServer *engine = NULL; // helper functions (messaging clients, loading content, making entities, running commands, etc)
IGameEventManager *gameeventmanager = NULL; // game events interface
IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players
IBotManager *botmanager = NULL; // game dll interface to interact with bots
IServerPluginHelpers *helpers = NULL; // special 3rd party plugin helpers from the engine
IUniformRandomStream *randomStr = NULL;
IEngineTrace *enginetrace = NULL;
CGlobalVars *gpGlobals = NULL;
// function to initialize any cvars/command in this plugin
void Bot_RunAll( void );
// useful helper func
inline bool FStrEq(const char *sz1, const char *sz2)
{
return(Q_stricmp(sz1, sz2) == 0);
}
//---------------------------------------------------------------------------------
// Purpose: a sample 3rd party plugin class
//---------------------------------------------------------------------------------
class CEmptyServerPlugin: public IServerPluginCallbacks, public IGameEventListener
{
public:
CEmptyServerPlugin();
~CEmptyServerPlugin();
// IServerPluginCallbacks methods
virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory );
virtual void Unload( void );
virtual void Pause( void );
virtual void UnPause( void );
virtual const char *GetPluginDescription( void );
virtual void LevelInit( char const *pMapName );
virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax );
virtual void GameFrame( bool simulating );
virtual void LevelShutdown( void );
virtual void ClientActive( edict_t *pEntity );
virtual void ClientDisconnect( edict_t *pEntity );
virtual void ClientPutInServer( edict_t *pEntity, char const *playername );
virtual void SetCommandClient( int index );
virtual void ClientSettingsChanged( edict_t *pEdict );
virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen );
virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args );
virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID );
virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue );
// IGameEventListener Interface
virtual void FireGameEvent( KeyValues * event );
virtual int GetCommandIndex() { return m_iClientCommandIndex; }
private:
int m_iClientCommandIndex;
};
//
// The plugin is a static singleton that is exported as an interface
//
CEmptyServerPlugin g_EmtpyServerPlugin;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEmptyServerPlugin, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, g_EmtpyServerPlugin );
//---------------------------------------------------------------------------------
// Purpose: constructor/destructor
//---------------------------------------------------------------------------------
CEmptyServerPlugin::CEmptyServerPlugin()
{
m_iClientCommandIndex = 0;
}
CEmptyServerPlugin::~CEmptyServerPlugin()
{
}
//---------------------------------------------------------------------------------
// Purpose: called when the plugin is loaded, load the interface we need from the engine
//---------------------------------------------------------------------------------
bool CEmptyServerPlugin::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory )
{
ConnectTier1Libraries( &interfaceFactory, 1 );
ConnectTier2Libraries( &interfaceFactory, 1 );
playerinfomanager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER,NULL);
if ( !playerinfomanager )
{
Warning( "Unable to load playerinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access specific player data
}
botmanager = (IBotManager *)gameServerFactory(INTERFACEVERSION_PLAYERBOTMANAGER, NULL);
if ( !botmanager )
{
Warning( "Unable to load botcontroller, ignoring\n" ); // this isn't fatal, we just won't be able to access specific bot functions
}
engine = (IVEngineServer*)interfaceFactory(INTERFACEVERSION_VENGINESERVER, NULL);
gameeventmanager = (IGameEventManager *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER,NULL);
helpers = (IServerPluginHelpers*)interfaceFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, NULL);
enginetrace = (IEngineTrace *)interfaceFactory(INTERFACEVERSION_ENGINETRACE_SERVER,NULL);
randomStr = (IUniformRandomStream *)interfaceFactory(VENGINE_SERVER_RANDOM_INTERFACE_VERSION, NULL);
// get the interfaces we want to use
if( ! ( engine && gameeventmanager && g_pFullFileSystem && helpers && enginetrace && randomStr ) )
{
return false; // we require all these interface to function
}
if ( playerinfomanager )
{
gpGlobals = playerinfomanager->GetGlobalVars();
}
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
ConVar_Register( 0 );
return true;
}
//---------------------------------------------------------------------------------
// Purpose: called when the plugin is unloaded (turned off)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::Unload( void )
{
gameeventmanager->RemoveListener( this ); // make sure we are unloaded from the event system
ConVar_Unregister( );
DisconnectTier2Libraries( );
DisconnectTier1Libraries( );
}
//---------------------------------------------------------------------------------
// Purpose: called when the plugin is paused (i.e should stop running but isn't unloaded)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::Pause( void )
{
}
//---------------------------------------------------------------------------------
// Purpose: called when the plugin is unpaused (i.e should start executing again)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::UnPause( void )
{
}
//---------------------------------------------------------------------------------
// Purpose: the name of this plugin, returned in "plugin_print" command
//---------------------------------------------------------------------------------
const char *CEmptyServerPlugin::GetPluginDescription( void )
{
return "Emtpy-Plugin, Valve";
}
//---------------------------------------------------------------------------------
// Purpose: called on level start
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::LevelInit( char const *pMapName )
{
Msg( "Level \"%s\" has been loaded\n", pMapName );
gameeventmanager->AddListener( this, true );
}
//---------------------------------------------------------------------------------
// Purpose: called on level start, when the server is ready to accept client connections
// edictCount is the number of entities in the level, clientMax is the max client count
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
{
}
//---------------------------------------------------------------------------------
// Purpose: called once per server frame, do recurring work here (like checking for timeouts)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::GameFrame( bool simulating )
{
if ( simulating )
{
Bot_RunAll();
}
}
//---------------------------------------------------------------------------------
// Purpose: called on level end (as the server is shutting down or going to a new map)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::LevelShutdown( void ) // !!!!this can get called multiple times per map change
{
gameeventmanager->RemoveListener( this );
}
//---------------------------------------------------------------------------------
// Purpose: called when a client spawns into a server (i.e as they begin to play)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::ClientActive( edict_t *pEntity )
{
}
//---------------------------------------------------------------------------------
// Purpose: called when a client leaves a server (or is timed out)
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::ClientDisconnect( edict_t *pEntity )
{
}
//---------------------------------------------------------------------------------
// Purpose: called on
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::ClientPutInServer( edict_t *pEntity, char const *playername )
{
KeyValues *kv = new KeyValues( "msg" );
kv->SetString( "title", "Hello" );
kv->SetString( "msg", "Hello there" );
kv->SetColor( "color", Color( 255, 0, 0, 255 ));
kv->SetInt( "level", 5);
kv->SetInt( "time", 10);
helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this );
kv->deleteThis();
}
//---------------------------------------------------------------------------------
// Purpose: called on level start
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::SetCommandClient( int index )
{
m_iClientCommandIndex = index;
}
//---------------------------------------------------------------------------------
// Purpose: called on level start
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::ClientSettingsChanged( edict_t *pEdict )
{
if ( playerinfomanager )
{
IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEdict );
const char * name = engine->GetClientConVarValue( engine->IndexOfEdict(pEdict), "name" );
if ( playerinfo && name && playerinfo->GetName() &&
Q_stricmp( name, playerinfo->GetName()) ) // playerinfo may be NULL if the MOD doesn't support access to player data
// OR if you are accessing the player before they are fully connected
{
char msg[128];
Q_snprintf( msg, sizeof(msg), "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() );
engine->ClientPrintf( pEdict, msg ); // this is the bad way to check this, the better option it to listen for the "player_changename" event in FireGameEvent()
// this is here to give a real example of how to use the playerinfo interface
}
}
}
//---------------------------------------------------------------------------------
// Purpose: called when a client joins a server
//---------------------------------------------------------------------------------
PLUGIN_RESULT CEmptyServerPlugin::ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen )
{
return PLUGIN_CONTINUE;
}
CON_COMMAND( DoAskConnect, "Server plugin example of using the ask connect dialog" )
{
if ( args.ArgC() < 2 )
{
Warning ( "DoAskConnect <server IP>\n" );
}
else
{
const char *pServerIP = args.Arg( 1 );
KeyValues *kv = new KeyValues( "menu" );
kv->SetString( "title", pServerIP ); // The IP address of the server to connect to goes in the "title" field.
kv->SetInt( "time", 3 );
for ( int i=1; i < gpGlobals->maxClients; i++ )
{
edict_t *pEdict = engine->PEntityOfEntIndex( i );
if ( pEdict )
{
helpers->CreateMessage( pEdict, DIALOG_ASKCONNECT, kv, &g_EmtpyServerPlugin );
}
}
kv->deleteThis();
}
}
//---------------------------------------------------------------------------------
// Purpose: called when a client types in a command (only a subset of commands however, not CON_COMMAND's)
//---------------------------------------------------------------------------------
PLUGIN_RESULT CEmptyServerPlugin::ClientCommand( edict_t *pEntity, const CCommand &args )
{
const char *pcmd = args[0];
if ( !pEntity || pEntity->IsFree() )
{
return PLUGIN_CONTINUE;
}
if ( FStrEq( pcmd, "menu" ) )
{
KeyValues *kv = new KeyValues( "menu" );
kv->SetString( "title", "You've got options, hit ESC" );
kv->SetInt( "level", 1 );
kv->SetColor( "color", Color( 255, 0, 0, 255 ));
kv->SetInt( "time", 20 );
kv->SetString( "msg", "Pick an option\nOr don't." );
for( int i = 1; i < 9; i++ )
{
char num[10], msg[10], cmd[10];
Q_snprintf( num, sizeof(num), "%i", i );
Q_snprintf( msg, sizeof(msg), "Option %i", i );
Q_snprintf( cmd, sizeof(cmd), "option%i", i );
KeyValues *item1 = kv->FindKey( num, true );
item1->SetString( "msg", msg );
item1->SetString( "command", cmd );
}
helpers->CreateMessage( pEntity, DIALOG_MENU, kv, this );
kv->deleteThis();
return PLUGIN_STOP; // we handled this function
}
else if ( FStrEq( pcmd, "rich" ) )
{
KeyValues *kv = new KeyValues( "menu" );
kv->SetString( "title", "A rich message" );
kv->SetInt( "level", 1 );
kv->SetInt( "time", 20 );
kv->SetString( "msg", "This is a long long long text string.\n\nIt also has line breaks." );
helpers->CreateMessage( pEntity, DIALOG_TEXT, kv, this );
kv->deleteThis();
return PLUGIN_STOP; // we handled this function
}
else if ( FStrEq( pcmd, "msg" ) )
{
KeyValues *kv = new KeyValues( "menu" );
kv->SetString( "title", "Just a simple hello" );
kv->SetInt( "level", 1 );
kv->SetInt( "time", 20 );
helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this );
kv->deleteThis();
return PLUGIN_STOP; // we handled this function
}
else if ( FStrEq( pcmd, "entry" ) )
{
KeyValues *kv = new KeyValues( "entry" );
kv->SetString( "title", "Stuff" );
kv->SetString( "msg", "Enter something" );
kv->SetString( "command", "say" ); // anything they enter into the dialog turns into a say command
kv->SetInt( "level", 1 );
kv->SetInt( "time", 20 );
helpers->CreateMessage( pEntity, DIALOG_ENTRY, kv, this );
kv->deleteThis();
return PLUGIN_STOP; // we handled this function
}
return PLUGIN_CONTINUE;
}
//---------------------------------------------------------------------------------
// Purpose: called when a client is authenticated
//---------------------------------------------------------------------------------
PLUGIN_RESULT CEmptyServerPlugin::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID )
{
return PLUGIN_CONTINUE;
}
//---------------------------------------------------------------------------------
// Purpose: called when a cvar value query is finished
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue )
{
Msg( "Cvar query (cookie: %d, status: %d) - name: %s, value: %s\n", iCookie, eStatus, pCvarName, pCvarValue );
}
//---------------------------------------------------------------------------------
// Purpose: called when an event is fired
//---------------------------------------------------------------------------------
void CEmptyServerPlugin::FireGameEvent( KeyValues * event )
{
const char * name = event->GetName();
Msg( "CEmptyServerPlugin::FireGameEvent: Got event \"%s\"\n", name );
}
//---------------------------------------------------------------------------------
// Purpose: an example of how to implement a new command
//---------------------------------------------------------------------------------
CON_COMMAND( empty_version, "prints the version of the empty plugin" )
{
Msg( "Version:1.0.0.0\n" );
}
CON_COMMAND( empty_log, "logs the version of the empty plugin" )
{
engine->LogPrint( "Version:1.0.0.0\n" );
}
//---------------------------------------------------------------------------------
// Purpose: an example cvar
//---------------------------------------------------------------------------------
static ConVar empty_cvar("plugin_empty", "0", 0, "Example plugin cvar");