From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- .../utils/serverplugin_sample/serverplugin_bot.cpp | 766 ++++---- .../serverplugin_sample/serverplugin_empty.cpp | 1844 ++++++++++---------- .../serverplugin_sample/serverplugin_empty.vpc | 124 +- 3 files changed, 1367 insertions(+), 1367 deletions(-) (limited to 'mp/src/utils/serverplugin_sample') diff --git a/mp/src/utils/serverplugin_sample/serverplugin_bot.cpp b/mp/src/utils/serverplugin_sample/serverplugin_bot.cpp index 250bf149..7d900cfd 100644 --- a/mp/src/utils/serverplugin_sample/serverplugin_bot.cpp +++ b/mp/src/utils/serverplugin_sample/serverplugin_bot.cpp @@ -1,383 +1,383 @@ -//========= Copyright 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 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 ); - - cmd.viewangles = pBot->m_BotInterface->GetLocalAngles(); - cmd.upmove = 0; - cmd.impulse = 0; - } - - pBot->m_BotInterface->RunPlayerMove( &cmd ); -} - - +//========= Copyright 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 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 ); + + cmd.viewangles = pBot->m_BotInterface->GetLocalAngles(); + cmd.upmove = 0; + cmd.impulse = 0; + } + + pBot->m_BotInterface->RunPlayerMove( &cmd ); +} + + diff --git a/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp b/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp index ff82b5f6..42e4c1d3 100644 --- a/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp +++ b/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp @@ -1,922 +1,922 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#include - -//#define GAME_DLL -#ifdef GAME_DLL -#include "cbase.h" -#endif - -#include -#include "interface.h" -#include "filesystem.h" -#include "engine/iserverplugin.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" -#include "game/server/pluginvariant.h" -#include "game/server/iplayerinfo.h" -#include "game/server/ientityinfo.h" -#include "game/server/igameinfo.h" - -//#define SAMPLE_TF2_PLUGIN -#ifdef SAMPLE_TF2_PLUGIN -#include "tf/tf_shareddefs.h" -#endif -// 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 -#ifndef GAME_DLL -#define gameeventmanager gameeventmanager_ -#endif -IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players -IEntityInfoManager *entityinfomanager = NULL; // game dll interface to interact with all entities (like IPlayerInfo) -IGameInfoManager *gameinfomanager = NULL; // game dll interface to get data from game rules directly -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 -#ifndef GAME_DLL -inline bool FStrEq(const char *sz1, const char *sz2) -{ - return(Q_stricmp(sz1, sz2) == 0); -} -#endif -//--------------------------------------------------------------------------------- -// 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 ); - virtual void OnEdictAllocated( edict_t *edict ); - virtual void OnEdictFreed( const edict_t *edict ); - - // 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 ); - - entityinfomanager = (IEntityInfoManager *)gameServerFactory(INTERFACEVERSION_ENTITYINFOMANAGER,NULL); - if ( !entityinfomanager ) - { - Warning( "Unable to load entityinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access entity data - } - - 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 - } - gameinfomanager = (IGameInfoManager *)gameServerFactory(INTERFACEVERSION_GAMEINFOMANAGER, NULL); - if (!gameinfomanager) - { - Warning( "Unable to load gameinfomanager, ignoring\n" ); - } - - 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 V2, 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; -} - -void ClientPrint( edict_t *pEdict, char *format, ... ) -{ - va_list argptr; - static char string[1024]; - - va_start (argptr, format); - Q_vsnprintf(string, sizeof(string), format,argptr); - va_end (argptr); - - engine->ClientPrintf( pEdict, string ); -} -//--------------------------------------------------------------------------------- -// 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" ); - - // CAN'T use Q_stricmp here, this dll is made by 3rd parties and may not link to tier0/vstdlib - if ( playerinfo && name && playerinfo->GetName() && - 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 - { - ClientPrint( pEdict, "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() ); - // 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 \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(); - } -} - -#ifdef SAMPLE_TF2_PLUGIN -const char *classNames[] = -{ - "unknown", - "scout", - "sniper", - "soldier", - "demoman", - "medic", - "heavy weapons guy", - "pyro", - "spy", - "engineer", -}; - -bool TFPlayerHasCondition( int inBits, int condition ) -{ - Assert( condition >= 0 && condition < TF_COND_LAST ); - - return ( ( inBits & (1<GetPlayerInfo( pEntity ); - if (!playerinfo) - { - Msg("couldn't get playerinfo\n"); - return; - } - - Msg("Sentry Status:\n"); - pluginvariant value; - pluginvariant emptyVariant; - edict_t *pSentry = NULL; - if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_SENTRY, value, emptyVariant)) - { - pSentry = engine->PEntityOfEntIndex( value.Int() ); - if (!pSentry) - { - Warning("couldn't attain sentry gun entity\n"); - return; - } - } - else - { - Msg("No Sentrygun built.\n"); - return; - - } - IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pSentry ); - if (!entinfo) - { - Warning("couldn't get entinfo for sentry gun\n"); - return; - } - - if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_SENTRY, value, emptyVariant)) - { - if (value.Bool()) - Msg("Sentry Under Construction...\n"); - } - if (playerinfo->GetCustomInfo(TFPLAYERINFO_UPGRADING_SENTRY, value, emptyVariant)) - { - if (value.Bool()) - Msg("Sentry Upgrading...\n"); - } - - int sentryLevel = 0; - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_LEVEL, value, emptyVariant)) - { - sentryLevel = value.Int(); - Msg("Sentry Level: %i\n", sentryLevel ); - } - else - Msg("Unable to retrive sentry level\n"); - - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_PROGRESS, value, emptyVariant)) - { - if (sentryLevel < 3) - { - int iMetal, iRequiredMetal; - iRequiredMetal = value.Int() & 0xFF; - iMetal = (value.Int()>>8) & 0xFF; - Msg("%i / %i Metal Required for Sentry Level %i\n", iMetal, iRequiredMetal, sentryLevel+1); - } - else - Msg("Sentry cannot be upgraded further.\n"); - } - - Msg("Health: %i\n", entinfo->GetHealth() ); - - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_KILLS, value, emptyVariant)) - Msg("Kills: %i\n", value.Int() ); - else - Msg("Unable to retrieve sentry kills\n"); - - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_SHELLS, value, emptyVariant)) - { - int iShells, iMaxShells; - iMaxShells = value.Int() & 0xFF; - iShells = (value.Int()>>8) & 0xFF; - Msg("Shells: %i / %i\n", iShells, iMaxShells); - } - if (sentryLevel > 2) - { - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_ROCKETS, value, emptyVariant)) - { - int iRockets, iMaxRockets; - iMaxRockets = value.Int() & 0xFF; - iRockets = (value.Int()>>8) & 0xFF; - Msg("Rockets: %i / %i\n", iRockets, iMaxRockets); - } - } - -} -void DispenserStatus( edict_t *pEntity ) -{ - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); - if (!playerinfo) - { - Msg("couldn't get playerinfo\n"); - return; - } - - Msg("Dispenser Status:\n"); - pluginvariant value; - pluginvariant emptyVariant; - edict_t *pDispenser = NULL; - if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_DISPENSER, value, emptyVariant)) - { - pDispenser = engine->PEntityOfEntIndex( value.Int() ); - if (!pDispenser) - { - Warning("couldn't attain dispenser entity\n"); - return; - } - } - else - { - Msg("No dispenser built.\n"); - return; - } - IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pDispenser ); - if (!entinfo) - { - Warning("couldn't get entinfo for dispenser\n"); - return; - } - if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_DISPENSER, value, emptyVariant)) - { - if (value.Bool()) - Msg("Dispenser Under Construction...\n"); - } - Msg("Health: %i\n", entinfo->GetHealth() ); - if (playerinfo->GetCustomInfo(TFPLAYERINFO_DISPENSER_METAL, value, emptyVariant)) - Msg("Metal: %i\n", value.Int() ); -} -void TeleporterStatus( edict_t *pEntity ) -{ - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); - if (!playerinfo) - { - Msg("couldn't get playerinfo\n"); - return; - } - - Msg("Teleporter Status:\n"); - - pluginvariant value; - pluginvariant emptyVariant; - edict_t *pEntrance = NULL; - edict_t *pExit = NULL; - if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_ENTRANCE, value, emptyVariant)) - { - pEntrance = engine->PEntityOfEntIndex( value.Int() ); - if (!pEntrance) - { - Warning("couldn't attain entrance entity\n"); - } - } - else - { - Msg("No Teleporter Entrance built.\n"); - } - if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_EXIT, value, emptyVariant)) - { - pExit = engine->PEntityOfEntIndex( value.Int() ); - if (!pExit) - { - Warning("couldn't attain exit entity\n"); - } - } - else - { - Msg("No Teleporter Entrance built.\n"); - } - IEntityInfo *entranceInfo = entityinfomanager->GetEntityInfo( pEntrance ); - if (!entranceInfo) - { - Warning("couldn't get entinfo for teleporter entrance\n"); - } - IEntityInfo *exitInfo = entityinfomanager->GetEntityInfo( pExit ); - if (!exitInfo) - { - Warning("couldn't get entinfo for teleporter exit\n"); - } - - if (pEntrance && entranceInfo) - { - if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_ENTRANCE, value, emptyVariant)) - { - if (value.Bool()) - Msg("Entrance Under Construction...\n"); - } - Msg("Entrance Health: %i\n", entranceInfo->GetHealth() ); - if (playerinfo->GetCustomInfo(TFPLAYERINFO_TELEPORTER_USES, value, emptyVariant)) - Msg("Entrance Used %i Times.\n", value.Int() ); - - } - if (pExit && exitInfo) - { - if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_EXIT, value, emptyVariant)) - { - if (value.Bool()) - Msg("Exit Under Construction...\n"); - } - Msg("Exit Health: %i\n", exitInfo->GetHealth() ); - } -} -void ClassStatus( edict_t *pEntity ) -{ - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); - if (!playerinfo) - { - Msg("couldn't get playerinfo\n"); - return; - } - int playerClassId = playerinfo->GetPlayerClassId(); - - Msg("Player Class: %s\n", playerinfo->GetPlayerClassName()); - pluginvariant conditionValue; - pluginvariant emptyVariant; - if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) - { - Warning("unable to retrieve conditions!\n"); - } - if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE )) - Msg("You are Invulnerable!\n"); - if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT )) - Msg("You are about to Teleport.\n"); - if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED )) - Msg("You have recently been teleported.\n"); - - switch(playerClassId) - { - default: - case TF_CLASS_MEDIC: - break; - case TF_CLASS_ENGINEER: - Msg("Building Information:\n"); - SentryStatus( pEntity ); - DispenserStatus( pEntity ); - TeleporterStatus( pEntity ); - break; - case TF_CLASS_SPY: - { - int disguiseClass = 0; - pluginvariant value; - - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_DISGUISEDAS, value, emptyVariant)) - disguiseClass = value.Int(); - - if ( TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ) - Msg("Disguising..\n"); - else if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ) - Msg("Disguised as: %s\n", classNames[disguiseClass] ); - - if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED )) - Msg("Cloaked!\n"); - if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_CLOAKCHARGELEVEL, value, emptyVariant)) - Msg("Cloak Charge Percent: %d\n", value.Float() ); - - break; - } - case TF_CLASS_DEMOMAN: - break; - } -} -const char *ctf_flagtype[] = -{ - "ctf", //TF_FLAGTYPE_CTF = 0, - "attack / defend", //TF_FLAGTYPE_ATTACK_DEFEND, - "territory control", //TF_FLAGTYPE_TERRITORY_CONTROL, - "invade", //TF_FLAGTYPE_INVADE, - "king of the hill", //TF_FLAGTYPE_KINGOFTHEHILL, -}; -const char *ctf_flagstatus[] = -{ - "unknown", - "At Home", - "Dropped", - "Stolen", -}; -void FlagStatus( edict_t *pPlayer ) -{ - IPlayerInfo *pInfo = playerinfomanager->GetPlayerInfo( pPlayer ); - if (!pInfo) - { - Msg( "couldn't get playerinfo\n" ); - return; - } - IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); - if (!gameInfo) - { - Msg( "couldn't get gameinfo\n" ); - } - - int gameType = gameInfo->GetInfo_GameType(); - - if (gameType != 1) - { - Msg( "Game is not CTF.\n" ); - return; - } - Msg( "===============================\n" ); - Msg( "Capture The Flag -- Flag Status\n" ); - Msg( "===============================\n" ); - pluginvariant value, options; - - edict_t *pFlag = NULL; - while ( (pFlag = entityinfomanager->FindEntityByClassname(pFlag, "item_teamflag")) != NULL ) - { - IEntityInfo *pFlagInfo = entityinfomanager->GetEntityInfo( pFlag ); - if (!pFlagInfo) - continue; - - Msg( "\nTeam %s's Flag\n", gameInfo->GetInfo_GetTeamName( pFlagInfo->GetTeamIndex() ) ); - options.SetInt(engine->IndexOfEdict(pFlag)); - if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_TYPE, value, options) ) - Msg( "Type: %s\n", ctf_flagtype[value.Int()] ); - if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_STATUS, value, options) ) - { - Msg( "Status: %s\n", ctf_flagstatus[value.Int()] ); - //Tony; if we're carried, find out who has us. - if (value.Int() == 3) - { - edict_t *pPlayer = pFlagInfo->GetOwner(); - if (pPlayer) - { - IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo( pPlayer ); - if (pPlayerInfo) - Msg( "Carried by: %s\n", pPlayerInfo->GetName() ); - } - } - } - } - - - Msg( "===============================\n" ); -} -#endif - -//--------------------------------------------------------------------------------- -// 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 - } -#ifdef SAMPLE_TF2_PLUGIN - else if ( FStrEq( pcmd, "gameinfo" ) ) - { - IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); - if (!gameInfo) - return PLUGIN_STOP; - - Msg("=== Game Information ===\n"); - Msg("Game Type: %i / %s\n", gameInfo->GetInfo_GameType(), gameInfo->GetInfo_GameTypeName() ); - int teamCount = gameInfo->GetInfo_GetTeamCount(); - Msg("Num Teams: %i\n", teamCount ); - - Msg("Player Counts:\n"); - for (int i = 0;iGetInfo_GetTeamName(i) ) - continue; - Msg("Team: %s, Players: %i\n", gameInfo->GetInfo_GetTeamName(i), gameInfo->GetInfo_NumPlayersOnTeam(i) ); - } - return PLUGIN_STOP; - - } - // Sample to use the new CustomInfo added to TF2 for plugins - else if ( FStrEq( pcmd, "tfcond" ) ) - { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); - if (!playerinfo) - return PLUGIN_STOP; - - pluginvariant conditionValue; - pluginvariant emptyVariant; - if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) - { - Msg("unable to retrieve conditions!\n"); - return PLUGIN_STOP; - } - - Msg("Disguising?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ? "yes" : "no" ); - Msg("Disguised?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ? "yes" : "no" ); - Msg("Stealthed?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED ) ? "yes" : "no" ); - Msg("Invulnerable?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE ) ? "yes" : "no" ); - Msg("Teleported Recently?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED ) ? "yes" : "no" ); - Msg("Selected for Teleportation?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT ) ? "yes" : "no" ); - Msg("On Fire?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_BURNING ) ? "yes" : "no" ); - - return PLUGIN_STOP; - } - else if ( FStrEq( pcmd, "sentry_status" ) ) - { - SentryStatus(pEntity); - return PLUGIN_STOP; - } - else if ( FStrEq( pcmd, "class_status" ) ) - { - ClassStatus(pEntity); - return PLUGIN_STOP; - } - else if ( FStrEq( pcmd, "flag_status" ) ) - { - FlagStatus(pEntity); - return PLUGIN_STOP; - } - #ifdef GAME_DLL - else if ( FStrEq( pcmd, "cbe_test" ) ) - { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); - if (!playerinfo) - return PLUGIN_STOP; - - CBaseEntity *pEnt = static_cast< CBaseEntity* >(entityinfomanager->GetEntity( pEntity )); - if (pEnt) - Msg("got a pointer to CBaseEntity..\n"); - Msg("attempting to print this entities modelname directly..\n"); - - Msg("ModelName: %s\n", STRING(pEnt->GetModelName()) ); - - return PLUGIN_STOP; - } - #endif -#endif - - - 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 ); -} -void CEmptyServerPlugin::OnEdictAllocated( edict_t *edict ) -{ -} -void CEmptyServerPlugin::OnEdictFreed( const edict_t *edict ) -{ -} - -//--------------------------------------------------------------------------------- -// 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:2.0.0.0\n" ); -} - -CON_COMMAND( empty_log, "logs the version of the empty plugin" ) -{ - engine->LogPrint( "Version:2.0.0.0\n" ); -} - -//--------------------------------------------------------------------------------- -// Purpose: an example cvar -//--------------------------------------------------------------------------------- -static ConVar empty_cvar("plugin_empty", "0", FCVAR_NOTIFY, "Example plugin cvar"); +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#include + +//#define GAME_DLL +#ifdef GAME_DLL +#include "cbase.h" +#endif + +#include +#include "interface.h" +#include "filesystem.h" +#include "engine/iserverplugin.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" +#include "game/server/pluginvariant.h" +#include "game/server/iplayerinfo.h" +#include "game/server/ientityinfo.h" +#include "game/server/igameinfo.h" + +//#define SAMPLE_TF2_PLUGIN +#ifdef SAMPLE_TF2_PLUGIN +#include "tf/tf_shareddefs.h" +#endif +// 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 +#ifndef GAME_DLL +#define gameeventmanager gameeventmanager_ +#endif +IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players +IEntityInfoManager *entityinfomanager = NULL; // game dll interface to interact with all entities (like IPlayerInfo) +IGameInfoManager *gameinfomanager = NULL; // game dll interface to get data from game rules directly +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 +#ifndef GAME_DLL +inline bool FStrEq(const char *sz1, const char *sz2) +{ + return(Q_stricmp(sz1, sz2) == 0); +} +#endif +//--------------------------------------------------------------------------------- +// 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 ); + virtual void OnEdictAllocated( edict_t *edict ); + virtual void OnEdictFreed( const edict_t *edict ); + + // 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 ); + + entityinfomanager = (IEntityInfoManager *)gameServerFactory(INTERFACEVERSION_ENTITYINFOMANAGER,NULL); + if ( !entityinfomanager ) + { + Warning( "Unable to load entityinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access entity data + } + + 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 + } + gameinfomanager = (IGameInfoManager *)gameServerFactory(INTERFACEVERSION_GAMEINFOMANAGER, NULL); + if (!gameinfomanager) + { + Warning( "Unable to load gameinfomanager, ignoring\n" ); + } + + 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 V2, 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; +} + +void ClientPrint( edict_t *pEdict, char *format, ... ) +{ + va_list argptr; + static char string[1024]; + + va_start (argptr, format); + Q_vsnprintf(string, sizeof(string), format,argptr); + va_end (argptr); + + engine->ClientPrintf( pEdict, string ); +} +//--------------------------------------------------------------------------------- +// 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" ); + + // CAN'T use Q_stricmp here, this dll is made by 3rd parties and may not link to tier0/vstdlib + if ( playerinfo && name && playerinfo->GetName() && + 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 + { + ClientPrint( pEdict, "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() ); + // 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 \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(); + } +} + +#ifdef SAMPLE_TF2_PLUGIN +const char *classNames[] = +{ + "unknown", + "scout", + "sniper", + "soldier", + "demoman", + "medic", + "heavy weapons guy", + "pyro", + "spy", + "engineer", +}; + +bool TFPlayerHasCondition( int inBits, int condition ) +{ + Assert( condition >= 0 && condition < TF_COND_LAST ); + + return ( ( inBits & (1<GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Sentry Status:\n"); + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pSentry = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_SENTRY, value, emptyVariant)) + { + pSentry = engine->PEntityOfEntIndex( value.Int() ); + if (!pSentry) + { + Warning("couldn't attain sentry gun entity\n"); + return; + } + } + else + { + Msg("No Sentrygun built.\n"); + return; + + } + IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pSentry ); + if (!entinfo) + { + Warning("couldn't get entinfo for sentry gun\n"); + return; + } + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_SENTRY, value, emptyVariant)) + { + if (value.Bool()) + Msg("Sentry Under Construction...\n"); + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_UPGRADING_SENTRY, value, emptyVariant)) + { + if (value.Bool()) + Msg("Sentry Upgrading...\n"); + } + + int sentryLevel = 0; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_LEVEL, value, emptyVariant)) + { + sentryLevel = value.Int(); + Msg("Sentry Level: %i\n", sentryLevel ); + } + else + Msg("Unable to retrive sentry level\n"); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_PROGRESS, value, emptyVariant)) + { + if (sentryLevel < 3) + { + int iMetal, iRequiredMetal; + iRequiredMetal = value.Int() & 0xFF; + iMetal = (value.Int()>>8) & 0xFF; + Msg("%i / %i Metal Required for Sentry Level %i\n", iMetal, iRequiredMetal, sentryLevel+1); + } + else + Msg("Sentry cannot be upgraded further.\n"); + } + + Msg("Health: %i\n", entinfo->GetHealth() ); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_KILLS, value, emptyVariant)) + Msg("Kills: %i\n", value.Int() ); + else + Msg("Unable to retrieve sentry kills\n"); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_SHELLS, value, emptyVariant)) + { + int iShells, iMaxShells; + iMaxShells = value.Int() & 0xFF; + iShells = (value.Int()>>8) & 0xFF; + Msg("Shells: %i / %i\n", iShells, iMaxShells); + } + if (sentryLevel > 2) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_ROCKETS, value, emptyVariant)) + { + int iRockets, iMaxRockets; + iMaxRockets = value.Int() & 0xFF; + iRockets = (value.Int()>>8) & 0xFF; + Msg("Rockets: %i / %i\n", iRockets, iMaxRockets); + } + } + +} +void DispenserStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Dispenser Status:\n"); + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pDispenser = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_DISPENSER, value, emptyVariant)) + { + pDispenser = engine->PEntityOfEntIndex( value.Int() ); + if (!pDispenser) + { + Warning("couldn't attain dispenser entity\n"); + return; + } + } + else + { + Msg("No dispenser built.\n"); + return; + } + IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pDispenser ); + if (!entinfo) + { + Warning("couldn't get entinfo for dispenser\n"); + return; + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_DISPENSER, value, emptyVariant)) + { + if (value.Bool()) + Msg("Dispenser Under Construction...\n"); + } + Msg("Health: %i\n", entinfo->GetHealth() ); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_DISPENSER_METAL, value, emptyVariant)) + Msg("Metal: %i\n", value.Int() ); +} +void TeleporterStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Teleporter Status:\n"); + + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pEntrance = NULL; + edict_t *pExit = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_ENTRANCE, value, emptyVariant)) + { + pEntrance = engine->PEntityOfEntIndex( value.Int() ); + if (!pEntrance) + { + Warning("couldn't attain entrance entity\n"); + } + } + else + { + Msg("No Teleporter Entrance built.\n"); + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_EXIT, value, emptyVariant)) + { + pExit = engine->PEntityOfEntIndex( value.Int() ); + if (!pExit) + { + Warning("couldn't attain exit entity\n"); + } + } + else + { + Msg("No Teleporter Entrance built.\n"); + } + IEntityInfo *entranceInfo = entityinfomanager->GetEntityInfo( pEntrance ); + if (!entranceInfo) + { + Warning("couldn't get entinfo for teleporter entrance\n"); + } + IEntityInfo *exitInfo = entityinfomanager->GetEntityInfo( pExit ); + if (!exitInfo) + { + Warning("couldn't get entinfo for teleporter exit\n"); + } + + if (pEntrance && entranceInfo) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_ENTRANCE, value, emptyVariant)) + { + if (value.Bool()) + Msg("Entrance Under Construction...\n"); + } + Msg("Entrance Health: %i\n", entranceInfo->GetHealth() ); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_TELEPORTER_USES, value, emptyVariant)) + Msg("Entrance Used %i Times.\n", value.Int() ); + + } + if (pExit && exitInfo) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_EXIT, value, emptyVariant)) + { + if (value.Bool()) + Msg("Exit Under Construction...\n"); + } + Msg("Exit Health: %i\n", exitInfo->GetHealth() ); + } +} +void ClassStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + int playerClassId = playerinfo->GetPlayerClassId(); + + Msg("Player Class: %s\n", playerinfo->GetPlayerClassName()); + pluginvariant conditionValue; + pluginvariant emptyVariant; + if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) + { + Warning("unable to retrieve conditions!\n"); + } + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE )) + Msg("You are Invulnerable!\n"); + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT )) + Msg("You are about to Teleport.\n"); + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED )) + Msg("You have recently been teleported.\n"); + + switch(playerClassId) + { + default: + case TF_CLASS_MEDIC: + break; + case TF_CLASS_ENGINEER: + Msg("Building Information:\n"); + SentryStatus( pEntity ); + DispenserStatus( pEntity ); + TeleporterStatus( pEntity ); + break; + case TF_CLASS_SPY: + { + int disguiseClass = 0; + pluginvariant value; + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_DISGUISEDAS, value, emptyVariant)) + disguiseClass = value.Int(); + + if ( TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ) + Msg("Disguising..\n"); + else if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ) + Msg("Disguised as: %s\n", classNames[disguiseClass] ); + + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED )) + Msg("Cloaked!\n"); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_CLOAKCHARGELEVEL, value, emptyVariant)) + Msg("Cloak Charge Percent: %d\n", value.Float() ); + + break; + } + case TF_CLASS_DEMOMAN: + break; + } +} +const char *ctf_flagtype[] = +{ + "ctf", //TF_FLAGTYPE_CTF = 0, + "attack / defend", //TF_FLAGTYPE_ATTACK_DEFEND, + "territory control", //TF_FLAGTYPE_TERRITORY_CONTROL, + "invade", //TF_FLAGTYPE_INVADE, + "king of the hill", //TF_FLAGTYPE_KINGOFTHEHILL, +}; +const char *ctf_flagstatus[] = +{ + "unknown", + "At Home", + "Dropped", + "Stolen", +}; +void FlagStatus( edict_t *pPlayer ) +{ + IPlayerInfo *pInfo = playerinfomanager->GetPlayerInfo( pPlayer ); + if (!pInfo) + { + Msg( "couldn't get playerinfo\n" ); + return; + } + IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); + if (!gameInfo) + { + Msg( "couldn't get gameinfo\n" ); + } + + int gameType = gameInfo->GetInfo_GameType(); + + if (gameType != 1) + { + Msg( "Game is not CTF.\n" ); + return; + } + Msg( "===============================\n" ); + Msg( "Capture The Flag -- Flag Status\n" ); + Msg( "===============================\n" ); + pluginvariant value, options; + + edict_t *pFlag = NULL; + while ( (pFlag = entityinfomanager->FindEntityByClassname(pFlag, "item_teamflag")) != NULL ) + { + IEntityInfo *pFlagInfo = entityinfomanager->GetEntityInfo( pFlag ); + if (!pFlagInfo) + continue; + + Msg( "\nTeam %s's Flag\n", gameInfo->GetInfo_GetTeamName( pFlagInfo->GetTeamIndex() ) ); + options.SetInt(engine->IndexOfEdict(pFlag)); + if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_TYPE, value, options) ) + Msg( "Type: %s\n", ctf_flagtype[value.Int()] ); + if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_STATUS, value, options) ) + { + Msg( "Status: %s\n", ctf_flagstatus[value.Int()] ); + //Tony; if we're carried, find out who has us. + if (value.Int() == 3) + { + edict_t *pPlayer = pFlagInfo->GetOwner(); + if (pPlayer) + { + IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo( pPlayer ); + if (pPlayerInfo) + Msg( "Carried by: %s\n", pPlayerInfo->GetName() ); + } + } + } + } + + + Msg( "===============================\n" ); +} +#endif + +//--------------------------------------------------------------------------------- +// 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 + } +#ifdef SAMPLE_TF2_PLUGIN + else if ( FStrEq( pcmd, "gameinfo" ) ) + { + IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); + if (!gameInfo) + return PLUGIN_STOP; + + Msg("=== Game Information ===\n"); + Msg("Game Type: %i / %s\n", gameInfo->GetInfo_GameType(), gameInfo->GetInfo_GameTypeName() ); + int teamCount = gameInfo->GetInfo_GetTeamCount(); + Msg("Num Teams: %i\n", teamCount ); + + Msg("Player Counts:\n"); + for (int i = 0;iGetInfo_GetTeamName(i) ) + continue; + Msg("Team: %s, Players: %i\n", gameInfo->GetInfo_GetTeamName(i), gameInfo->GetInfo_NumPlayersOnTeam(i) ); + } + return PLUGIN_STOP; + + } + // Sample to use the new CustomInfo added to TF2 for plugins + else if ( FStrEq( pcmd, "tfcond" ) ) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + return PLUGIN_STOP; + + pluginvariant conditionValue; + pluginvariant emptyVariant; + if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) + { + Msg("unable to retrieve conditions!\n"); + return PLUGIN_STOP; + } + + Msg("Disguising?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ? "yes" : "no" ); + Msg("Disguised?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ? "yes" : "no" ); + Msg("Stealthed?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED ) ? "yes" : "no" ); + Msg("Invulnerable?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE ) ? "yes" : "no" ); + Msg("Teleported Recently?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED ) ? "yes" : "no" ); + Msg("Selected for Teleportation?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT ) ? "yes" : "no" ); + Msg("On Fire?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_BURNING ) ? "yes" : "no" ); + + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "sentry_status" ) ) + { + SentryStatus(pEntity); + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "class_status" ) ) + { + ClassStatus(pEntity); + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "flag_status" ) ) + { + FlagStatus(pEntity); + return PLUGIN_STOP; + } + #ifdef GAME_DLL + else if ( FStrEq( pcmd, "cbe_test" ) ) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + return PLUGIN_STOP; + + CBaseEntity *pEnt = static_cast< CBaseEntity* >(entityinfomanager->GetEntity( pEntity )); + if (pEnt) + Msg("got a pointer to CBaseEntity..\n"); + Msg("attempting to print this entities modelname directly..\n"); + + Msg("ModelName: %s\n", STRING(pEnt->GetModelName()) ); + + return PLUGIN_STOP; + } + #endif +#endif + + + 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 ); +} +void CEmptyServerPlugin::OnEdictAllocated( edict_t *edict ) +{ +} +void CEmptyServerPlugin::OnEdictFreed( const edict_t *edict ) +{ +} + +//--------------------------------------------------------------------------------- +// 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:2.0.0.0\n" ); +} + +CON_COMMAND( empty_log, "logs the version of the empty plugin" ) +{ + engine->LogPrint( "Version:2.0.0.0\n" ); +} + +//--------------------------------------------------------------------------------- +// Purpose: an example cvar +//--------------------------------------------------------------------------------- +static ConVar empty_cvar("plugin_empty", "0", FCVAR_NOTIFY, "Example plugin cvar"); diff --git a/mp/src/utils/serverplugin_sample/serverplugin_empty.vpc b/mp/src/utils/serverplugin_sample/serverplugin_empty.vpc index a4bc5380..0d584af5 100644 --- a/mp/src/utils/serverplugin_sample/serverplugin_empty.vpc +++ b/mp/src/utils/serverplugin_sample/serverplugin_empty.vpc @@ -1,62 +1,62 @@ -//----------------------------------------------------------------------------- -// SERVERPLUGIN_EMPTY.VPC -// -// Project Script -//----------------------------------------------------------------------------- - -$Macro SRCDIR "..\.." -$Macro OUTBINDIR "$SRCDIR\..\game\bin" - -$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" - -$Configuration -{ - $Compiler - { - $AdditionalIncludeDirectories "$BASE,$SRCDIR\game\server,$SRCDIR\game\shared" - $PreprocessorDefinitions "$BASE;serverplugin_emptyONLY;_MBCS" - } - - $Linker - { - $AdditionalDependencies "$BASE odbc32.lib odbccp32.lib" - } -} - -$Project "Serverplugin_empty" -{ - $Folder "Source Files" - { - $File "serverplugin_bot.cpp" - $File "serverplugin_empty.cpp" - } - - $Folder "Header Files" - { - $File "$SRCDIR\public\tier0\basetypes.h" - $File "$SRCDIR\public\Color.h" - $File "$SRCDIR\public\tier0\dbg.h" - $File "$SRCDIR\public\eiface.h" - $File "$SRCDIR\public\filesystem.h" - $File "$SRCDIR\public\tier0\icommandline.h" - $File "$SRCDIR\public\igameevents.h" - $File "$SRCDIR\public\tier1\interface.h" - $File "$SRCDIR\public\game\server\iplayerinfo.h" - $File "$SRCDIR\public\engine\iserverplugin.h" - $File "$SRCDIR\public\tier1\KeyValues.h" - $File "$SRCDIR\public\tier0\mem.h" - $File "$SRCDIR\public\tier0\memalloc.h" - $File "$SRCDIR\public\tier0\memdbgon.h" - $File "$SRCDIR\public\tier1\strtools.h" - $File "$SRCDIR\public\tier1\utlbuffer.h" - $File "$SRCDIR\public\tier1\utlmemory.h" - $File "$SRCDIR\public\tier1\utlvector.h" - $File "$SRCDIR\public\vstdlib\vstdlib.h" - } - - $Folder "Link Libraries" - { - $Lib mathlib - $Lib tier2 - } -} +//----------------------------------------------------------------------------- +// SERVERPLUGIN_EMPTY.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,$SRCDIR\game\server,$SRCDIR\game\shared" + $PreprocessorDefinitions "$BASE;serverplugin_emptyONLY;_MBCS" + } + + $Linker + { + $AdditionalDependencies "$BASE odbc32.lib odbccp32.lib" + } +} + +$Project "Serverplugin_empty" +{ + $Folder "Source Files" + { + $File "serverplugin_bot.cpp" + $File "serverplugin_empty.cpp" + } + + $Folder "Header Files" + { + $File "$SRCDIR\public\tier0\basetypes.h" + $File "$SRCDIR\public\Color.h" + $File "$SRCDIR\public\tier0\dbg.h" + $File "$SRCDIR\public\eiface.h" + $File "$SRCDIR\public\filesystem.h" + $File "$SRCDIR\public\tier0\icommandline.h" + $File "$SRCDIR\public\igameevents.h" + $File "$SRCDIR\public\tier1\interface.h" + $File "$SRCDIR\public\game\server\iplayerinfo.h" + $File "$SRCDIR\public\engine\iserverplugin.h" + $File "$SRCDIR\public\tier1\KeyValues.h" + $File "$SRCDIR\public\tier0\mem.h" + $File "$SRCDIR\public\tier0\memalloc.h" + $File "$SRCDIR\public\tier0\memdbgon.h" + $File "$SRCDIR\public\tier1\strtools.h" + $File "$SRCDIR\public\tier1\utlbuffer.h" + $File "$SRCDIR\public\tier1\utlmemory.h" + $File "$SRCDIR\public\tier1\utlvector.h" + $File "$SRCDIR\public\vstdlib\vstdlib.h" + } + + $Folder "Link Libraries" + { + $Lib mathlib + $Lib tier2 + } +} -- cgit v1.2.3