forked from alliedmodders/hl2sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add files via upload (alliedmodders#37)
Added serverplugin_sample from source sdk as well as VC2010 project to build a working VSP sample Co-authored-by: hackspider <[email protected]>
- Loading branch information
1 parent
259877e
commit e2e62c5
Showing
4 changed files
with
1,501 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,390 @@ | ||
//========= 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" ); | ||
|
||
inline edict_t *PEntityOfEntIndex(int iEntIndex) | ||
{ | ||
if(iEntIndex >= 0 && iEntIndex < gpGlobals->maxEntities) | ||
return (edict_t *)(gpGlobals->pEdicts + iEntIndex); | ||
|
||
return NULL; | ||
} | ||
|
||
// 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( 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 ); | ||
} | ||
|
||
|
Oops, something went wrong.