2002-05-24 00:00:00 +00:00
// Copyright (C) 2001-2002 Raven Software.
//
# include "g_local.h"
# include "../../ui/menudef.h"
int AcceptBotCommand ( char * cmd , gentity_t * pl ) ;
/*
= = = = = = = = = = = = = = = = = =
DeathmatchScoreboardMessage
= = = = = = = = = = = = = = = = = =
*/
void DeathmatchScoreboardMessage ( gentity_t * ent )
{
char entry [ 1024 ] ;
char string [ 1400 ] ;
int stringlength ;
int i , j ;
gclient_t * cl ;
int numSorted ;
// send the latest information on all clients
string [ 0 ] = 0 ;
stringlength = 0 ;
numSorted = level . numConnectedClients ;
for ( i = 0 ; i < numSorted ; i + + )
{
int ping ;
cl = & level . clients [ level . sortedClients [ i ] ] ;
if ( cl - > pers . connected = = CON_CONNECTING )
{
ping = - 1 ;
}
else
{
ping = cl - > ps . ping < 999 ? cl - > ps . ping : 999 ;
}
Com_sprintf ( entry , sizeof ( entry ) ,
" %i %i %i %i %i %i %i %i %i " ,
level . sortedClients [ i ] ,
cl - > sess . score ,
cl - > sess . kills ,
cl - > sess . deaths ,
ping ,
( level . time - cl - > pers . enterTime ) / 60000 ,
( cl - > sess . ghost | | cl - > ps . pm_type = = PM_DEAD ) ? qtrue : qfalse ,
g_entities [ level . sortedClients [ i ] ] . s . gametypeitems ,
g_teamkillDamageMax . integer ? 100 * cl - > sess . teamkillDamage / g_teamkillDamageMax . integer : 0
) ;
j = strlen ( entry ) ;
if ( stringlength + j > 1022 )
{
break ;
}
strcpy ( string + stringlength , entry ) ;
stringlength + = j ;
}
trap_SendServerCommand ( ent - g_entities , va ( " scores %i %i %i%s " , i ,
level . teamScores [ TEAM_RED ] ,
level . teamScores [ TEAM_BLUE ] ,
string ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Score_f
Request current scoreboard information
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Score_f ( gentity_t * ent )
{
DeathmatchScoreboardMessage ( ent ) ;
}
/*
= = = = = = = = = = = = = = = = = =
CheatsOk
= = = = = = = = = = = = = = = = = =
*/
qboolean CheatsOk ( gentity_t * ent ) {
if ( ! g_cheats . integer ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" Cheats are not enabled on this server. \n \" " ) ) ;
return qfalse ;
}
if ( ent - > health < = 0 ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" You must be alive to use this command. \n \" " ) ) ;
return qfalse ;
}
return qtrue ;
}
/*
= = = = = = = = = = = = = = = = = =
ConcatArgs
= = = = = = = = = = = = = = = = = =
*/
char * ConcatArgs ( int start ) {
int i , c , tlen ;
static char line [ MAX_STRING_CHARS ] ;
int len ;
char arg [ MAX_STRING_CHARS ] ;
len = 0 ;
c = trap_Argc ( ) ;
for ( i = start ; i < c ; i + + ) {
trap_Argv ( i , arg , sizeof ( arg ) ) ;
tlen = strlen ( arg ) ;
if ( len + tlen > = MAX_STRING_CHARS - 1 ) {
break ;
}
memcpy ( line + len , arg , tlen ) ;
len + = tlen ;
if ( i ! = c - 1 ) {
line [ len ] = ' ' ;
len + + ;
}
}
line [ len ] = 0 ;
return line ;
}
/*
= = = = = = = = = = = = = = = = = =
SanitizeString
Remove case and control characters
= = = = = = = = = = = = = = = = = =
*/
void SanitizeString ( char * in , char * out ) {
while ( * in ) {
if ( * in = = 27 ) {
in + = 2 ; // skip color code
continue ;
}
if ( * in < 32 ) {
in + + ;
continue ;
}
* out + + = tolower ( * in + + ) ;
}
* out = 0 ;
}
/*
= = = = = = = = = = = = = = = = = =
G_ClientNumberFromName
Finds the client number of the client with the given name
= = = = = = = = = = = = = = = = = =
*/
int G_ClientNumberFromName ( const char * name )
{
char s2 [ MAX_STRING_CHARS ] ;
char n2 [ MAX_STRING_CHARS ] ;
int i ;
gclient_t * cl ;
// check for a name match
SanitizeString ( ( char * ) name , s2 ) ;
for ( i = 0 , cl = level . clients ; i < level . numConnectedClients ; i + + , cl + + )
{
SanitizeString ( cl - > pers . netname , n2 ) ;
if ( ! strcmp ( n2 , s2 ) )
{
return i ;
}
}
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = =
ClientNumberFromString
Returns a player number for either a number or name string
Returns - 1 if invalid
= = = = = = = = = = = = = = = = = =
*/
int ClientNumberFromString ( gentity_t * to , char * s ) {
gclient_t * cl ;
int idnum ;
char s2 [ MAX_STRING_CHARS ] ;
char n2 [ MAX_STRING_CHARS ] ;
// numeric values are just slot numbers
if ( s [ 0 ] > = ' 0 ' & & s [ 0 ] < = ' 9 ' ) {
idnum = atoi ( s ) ;
if ( idnum < 0 | | idnum > = level . maxclients ) {
trap_SendServerCommand ( to - g_entities , va ( " print \" Bad client slot: %i \n \" " , idnum ) ) ;
return - 1 ;
}
cl = & level . clients [ idnum ] ;
if ( cl - > pers . connected ! = CON_CONNECTED ) {
trap_SendServerCommand ( to - g_entities , va ( " print \" Client %i is not active \n \" " , idnum ) ) ;
return - 1 ;
}
return idnum ;
}
// check for a name match
SanitizeString ( s , s2 ) ;
for ( idnum = 0 , cl = level . clients ; idnum < level . maxclients ; idnum + + , cl + + ) {
if ( cl - > pers . connected ! = CON_CONNECTED ) {
continue ;
}
SanitizeString ( cl - > pers . netname , n2 ) ;
if ( ! strcmp ( n2 , s2 ) ) {
return idnum ;
}
}
trap_SendServerCommand ( to - g_entities , va ( " print \" User %s is not on the server \n \" " , s ) ) ;
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Drop_f
Drops the currenty selected weapon
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Drop_f ( gentity_t * ent )
{
gentity_t * dropped ;
// spectators cant drop anything since they dont have anything
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
return ;
}
// Ghosts and followers cant drop stuff
if ( ent - > client - > ps . pm_flags & ( PMF_GHOST | PMF_FOLLOW ) )
{
return ;
}
// Drop the weapon the client wanted to drop
dropped = G_DropWeapon ( ent , atoi ( ConcatArgs ( 1 ) ) , 3000 ) ;
if ( ! dropped )
{
return ;
}
}
2002-07-15 00:00:00 +00:00
/*
= = = = = = = = = = = = = = = = = =
Cmd_DropItem_f
Drops the gametype items the player is carrying
= = = = = = = = = = = = = = = = = =
*/
void Cmd_DropItem_f ( gentity_t * ent )
{
// spectators cant drop anything since they dont have anything
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
return ;
}
// Ghosts and followers cant drop stuff
if ( ent - > client - > ps . pm_flags & ( PMF_GHOST | PMF_FOLLOW ) )
{
return ;
}
// Nothing to drop
if ( ! ent - > client - > ps . stats [ STAT_GAMETYPE_ITEMS ] )
{
return ;
}
2002-09-24 00:00:00 +00:00
G_DropGametypeItems ( ent , 3000 ) ;
2002-07-15 00:00:00 +00:00
}
2002-05-24 00:00:00 +00:00
/*
= = = = = = = = = = = = = = = = = =
Cmd_Give_f
Give items to a client
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Give_f ( gentity_t * ent )
{
char * name ;
gitem_t * it ;
int i ;
qboolean give_all ;
gentity_t * it_ent ;
trace_t trace ;
char arg [ MAX_QPATH ] ;
int start ;
int end ;
int l ;
trap_Argv ( 1 , arg , sizeof ( arg ) ) ;
if ( ! Q_stricmp ( arg , " me " ) )
{
start = ent - > s . number ;
end = start + 1 ;
}
else if ( ! Q_stricmp ( arg , " all " ) )
{
start = 0 ;
end = MAX_CLIENTS ;
}
else
{
start = atoi ( arg ) ;
end = start + 1 ;
}
for ( l = start ; l < end ; l + + )
{
ent = & g_entities [ l ] ;
if ( ! ent - > inuse )
{
continue ;
}
if ( G_IsClientDead ( ent - > client ) )
{
continue ;
}
if ( ! CheatsOk ( ent ) ) {
return ;
}
name = ConcatArgs ( 2 ) ;
if ( Q_stricmp ( name , " all " ) = = 0 )
give_all = qtrue ;
else
give_all = qfalse ;
if ( give_all | | Q_stricmp ( name , " health " ) = = 0 )
{
ent - > health = MAX_HEALTH ;
if ( ! give_all )
continue ;
}
if ( give_all | | Q_stricmp ( name , " weapons " ) = = 0 )
{
ent - > client - > ps . stats [ STAT_WEAPONS ] = ( 1 < < WP_NUM_WEAPONS ) - 1 - ( 1 < < WP_NONE ) ;
if ( ! give_all )
continue ;
}
if ( give_all | | Q_stricmp ( name , " ammo " ) = = 0 )
{
for ( i = WP_NONE + 1 ; i < WP_NUM_WEAPONS ; i + + )
{
attackType_t a ;
for ( a = ATTACK_NORMAL ; a < ATTACK_MAX ; a + + )
{
ent - > client - > ps . clip [ a ] [ i ] = weaponData [ i ] . attack [ a ] . clipSize ;
ent - > client - > ps . ammo [ weaponData [ i ] . attack [ a ] . ammoIndex ] = ammoData [ weaponData [ i ] . attack [ a ] . ammoIndex ] . max ;
}
}
if ( ! give_all )
continue ;
}
if ( give_all | | Q_stricmp ( name , " armor " ) = = 0 )
{
ent - > client - > ps . stats [ STAT_ARMOR ] = MAX_ARMOR ;
if ( ! give_all )
continue ;
}
// spawn a specific item right on the player
if ( ! give_all )
{
it = BG_FindItem ( name ) ;
if ( ! it )
{
continue ;
}
if ( it - > giType = = IT_GAMETYPE )
{
continue ;
}
it_ent = G_Spawn ( ) ;
VectorCopy ( ent - > r . currentOrigin , it_ent - > s . origin ) ;
it_ent - > classname = it - > classname ;
G_SpawnItem ( it_ent , it ) ;
FinishSpawningItem ( it_ent ) ;
memset ( & trace , 0 , sizeof ( trace ) ) ;
Touch_Item ( it_ent , ent , & trace ) ;
if ( it_ent - > inuse )
{
G_FreeEntity ( it_ent ) ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_God_f
Sets client to godmode
argv ( 0 ) god
= = = = = = = = = = = = = = = = = =
*/
void Cmd_God_f ( gentity_t * ent )
{
char * msg ;
if ( ! CheatsOk ( ent ) ) {
return ;
}
ent - > flags ^ = FL_GODMODE ;
if ( ! ( ent - > flags & FL_GODMODE ) )
msg = " godmode OFF \n " ;
else
msg = " godmode ON \n " ;
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \" " , msg ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Notarget_f
Sets client to notarget
argv ( 0 ) notarget
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Notarget_f ( gentity_t * ent ) {
char * msg ;
if ( ! CheatsOk ( ent ) ) {
return ;
}
ent - > flags ^ = FL_NOTARGET ;
if ( ! ( ent - > flags & FL_NOTARGET ) )
msg = " notarget OFF \n " ;
else
msg = " notarget ON \n " ;
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \" " , msg ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Noclip_f
argv ( 0 ) noclip
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Noclip_f ( gentity_t * ent ) {
char * msg ;
if ( ! CheatsOk ( ent ) ) {
return ;
}
if ( ent - > client - > noclip ) {
msg = " noclip OFF \n " ;
} else {
msg = " noclip ON \n " ;
}
ent - > client - > noclip = ! ent - > client - > noclip ;
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \" " , msg ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_LevelShot_f
This is just to help generate the level pictures
for the menus . It goes to the intermission immediately
and sends over a command to the client to resize the view ,
hide the scoreboard , and take a special screenshot
= = = = = = = = = = = = = = = = = =
*/
void Cmd_LevelShot_f ( gentity_t * ent )
{
if ( ! CheatsOk ( ent ) )
{
return ;
}
BeginIntermission ( ) ;
trap_SendServerCommand ( ent - g_entities , " clientLevelShot " ) ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Kill_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Kill_f ( gentity_t * ent )
{
// No killing yourself if your a spectator
if ( G_IsClientSpectating ( ent - > client ) )
{
return ;
}
// No killing yourself if your dead
if ( G_IsClientDead ( ent - > client ) )
{
return ;
}
ent - > flags & = ~ FL_GODMODE ;
ent - > client - > ps . stats [ STAT_HEALTH ] = ent - > health = - 999 ;
player_die ( ent , ent , ent , 100000 , MOD_SUICIDE , HL_NONE , vec3_origin ) ;
}
/*
= = = = = = = = = = = = = = = = =
BroadCastTeamChange
Let everyone know about a team change
= = = = = = = = = = = = = = = = =
*/
void BroadcastTeamChange ( gclient_t * client , int oldTeam )
{
switch ( client - > sess . team )
{
case TEAM_RED :
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " joined the red team. \n \" " , client - > pers . netname ) ) ;
break ;
case TEAM_BLUE :
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " joined the blue team. \n \" " , client - > pers . netname ) ) ;
break ;
case TEAM_SPECTATOR :
if ( oldTeam ! = TEAM_SPECTATOR )
{
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " joined the spectators. \n \" " , client - > pers . netname ) ) ;
}
break ;
case TEAM_FREE :
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " joined the battle. \n \" " , client - > pers . netname ) ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = = = =
SetTeam
= = = = = = = = = = = = = = = = =
*/
void SetTeam ( gentity_t * ent , char * s , const char * identity )
{
int team ;
int oldTeam ;
gclient_t * client ;
int clientNum ;
spectatorState_t specState ;
int specClient ;
qboolean ghost ;
qboolean noOutfittingChange = qfalse ;
// see what change is requested
//
client = ent - > client ;
clientNum = client - level . clients ;
specClient = 0 ;
specState = SPECTATOR_NOT ;
// If an identity was specified then inject it into
// the clients userinfo
if ( identity )
{
char userinfo [ MAX_INFO_STRING ] ;
trap_GetUserinfo ( clientNum , userinfo , sizeof ( userinfo ) ) ;
if ( Q_stricmp ( identity , Info_ValueForKey ( userinfo , " identity " ) ) )
{
Info_SetValueForKey ( userinfo , " identity " , identity ) ;
Info_SetValueForKey ( userinfo , " team_identity " , identity ) ;
trap_SetUserinfo ( clientNum , userinfo ) ;
}
else
{
identity = NULL ;
}
}
if ( ! Q_stricmp ( s , " follow1 " ) )
{
team = TEAM_SPECTATOR ;
specState = SPECTATOR_FOLLOW ;
specClient = - 1 ;
}
else if ( ! Q_stricmp ( s , " follow2 " ) )
{
team = TEAM_SPECTATOR ;
specState = SPECTATOR_FOLLOW ;
specClient = - 2 ;
}
else if ( ! Q_stricmp ( s , " spectator " ) | | ! Q_stricmp ( s , " s " ) )
{
team = TEAM_SPECTATOR ;
specState = SPECTATOR_FREE ;
}
else if ( level . gametypeData - > teams )
{
// if running a team game, assign player to one of the teams
specState = SPECTATOR_NOT ;
if ( ! Q_stricmp ( s , " red " ) | | ! Q_stricmp ( s , " r " ) )
{
team = TEAM_RED ;
}
else if ( ! Q_stricmp ( s , " blue " ) | | ! Q_stricmp ( s , " b " ) )
{
team = TEAM_BLUE ;
}
else
{
// pick the team with the least number of players
team = PickTeam ( clientNum ) ;
}
if ( g_teamForceBalance . integer )
{
int counts [ TEAM_NUM_TEAMS ] ;
counts [ TEAM_BLUE ] = TeamCount ( ent - > client - > ps . clientNum , TEAM_BLUE , NULL ) ;
counts [ TEAM_RED ] = TeamCount ( ent - > client - > ps . clientNum , TEAM_RED , NULL ) ;
// We allow a spread of two
if ( team = = TEAM_RED & & counts [ TEAM_RED ] - counts [ TEAM_BLUE ] > 1 )
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
" cp \" Red team has too many players. \n \" " ) ;
// ignore the request
return ;
}
if ( team = = TEAM_BLUE & & counts [ TEAM_BLUE ] - counts [ TEAM_RED ] > 1 )
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
" cp \" Blue team has too many players. \n \" " ) ;
// ignore the request
return ;
}
// It's ok, the team we are switching to has less or same number of players
}
}
else
{
// force them to spectators if there aren't any spots free
team = TEAM_FREE ;
}
// override decision if limiting the players
if ( g_maxGameClients . integer > 0 & & level . numNonSpectatorClients > = g_maxGameClients . integer )
{
team = TEAM_SPECTATOR ;
}
// decide if we will allow the change
oldTeam = client - > sess . team ;
ghost = client - > sess . ghost ;
if ( team = = oldTeam & & team ! = TEAM_SPECTATOR )
{
if ( identity )
{
// get and distribute relevent paramters
client - > pers . identity = NULL ;
ClientUserinfoChanged ( clientNum ) ;
}
return ;
}
noOutfittingChange = ent - > client - > noOutfittingChange ;
// he starts at 'base'
client - > pers . teamState . state = TEAM_BEGIN ;
if ( oldTeam ! = TEAM_SPECTATOR )
{
if ( ghost )
{
G_StopGhosting ( ent ) ;
}
else if ( ! G_IsClientDead ( client ) )
{
// Kill him (makes sure he loses flags, etc)
ent - > flags & = ~ FL_GODMODE ;
ent - > client - > ps . stats [ STAT_HEALTH ] = ent - > health = 0 ;
player_die ( ent , ent , ent , 100000 , MOD_TEAMCHANGE , HL_NONE , vec3_origin ) ;
ent - > client - > sess . ghost = qfalse ;
}
}
// If respawn interval start as a ghost
if ( level . gametypeRespawnTime [ team ] )
{
ghost = qtrue ;
}
// they go to the end of the line
if ( team = = TEAM_SPECTATOR )
{
client - > sess . spectatorTime = level . time ;
}
client - > sess . team = team ;
client - > sess . spectatorState = specState ;
client - > sess . spectatorClient = specClient ;
2002-09-24 00:00:00 +00:00
// Kill any child entities of this client to protect against grenade team changers
G_FreeEnitityChildren ( ent ) ;
2002-05-24 00:00:00 +00:00
// Always spawn into a ctf game using a respawn timer.
if ( team ! = TEAM_SPECTATOR & & level . gametypeData - > respawnType = = RT_INTERVAL )
{
G_SetRespawnTimer ( ent ) ;
ghost = qtrue ;
}
BroadcastTeamChange ( client , oldTeam ) ;
// See if we should spawn as a ghost
if ( team ! = TEAM_SPECTATOR & & level . gametypeData - > respawnType = = RT_NONE )
{
// If there are ghosts already then spawn as a ghost because
// the game is already in progress.
2002-09-24 00:00:00 +00:00
if ( ! level . warmupTime & & ( level . gametypeJoinTime & & ( level . time - level . gametypeJoinTime ) > ( g_roundjointime . integer * 1000 ) ) | | noOutfittingChange | | client - > sess . noTeamChange )
2002-05-24 00:00:00 +00:00
{
ghost = qtrue ;
}
// Spectator to a team doesnt count
if ( oldTeam ! = TEAM_SPECTATOR )
{
client - > sess . noTeamChange = qtrue ;
}
}
// If a ghost, enforce it
if ( ghost )
{
// Make them a ghost again
if ( team ! = TEAM_SPECTATOR )
{
G_StartGhosting ( ent ) ;
// get and distribute relevent paramters
client - > pers . identity = NULL ;
ClientUserinfoChanged ( clientNum ) ;
CalculateRanks ( ) ;
return ;
}
}
// get and distribute relevent paramters
client - > pers . identity = NULL ;
ClientUserinfoChanged ( clientNum ) ;
CalculateRanks ( ) ;
// Begin the clients new life on the their new team
ClientBegin ( clientNum ) ;
}
/*
= = = = = = = = = = = = = = = = =
G_StartGhosting
Starts a client ghosting . This essentially will kill a player which is alive
= = = = = = = = = = = = = = = = =
*/
void G_StartGhosting ( gentity_t * ent )
{
int i ;
// Dont start ghosting if already ghosting
if ( ent - > client - > sess . ghost )
{
return ;
}
ent - > client - > sess . ghost = qtrue ;
ent - > client - > sess . spectatorState = SPECTATOR_FREE ;
ent - > client - > sess . spectatorClient = - 1 ;
ent - > client - > ps . pm_flags | = PMF_GHOST ;
ent - > client - > ps . stats [ STAT_HEALTH ] = 100 ;
ent - > client - > ps . pm_type = PM_SPECTATOR ;
ent - > client - > ps . pm_flags & = ~ PMF_FOLLOW ;
trap_UnlinkEntity ( ent ) ;
// stop any following clients
for ( i = 0 ; i < level . maxclients ; i + + )
{
if ( G_IsClientSpectating ( & level . clients [ i ] )
& & level . clients [ i ] . sess . spectatorState = = SPECTATOR_FOLLOW
& & level . clients [ i ] . sess . spectatorClient = = ent - > s . number )
{
G_StopFollowing ( & g_entities [ i ] ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
G_StopGhosting
Stops a client from ghosting . The client will be dead after this
call
= = = = = = = = = = = = = = = = =
*/
void G_StopGhosting ( gentity_t * ent )
{
// Dont stop someone who isnt ghosting in the first place
if ( ! ent - > client - > sess . ghost )
{
return ;
}
ent - > client - > sess . ghost = qfalse ;
ent - > client - > ps . pm_flags & = ~ PMF_GHOST ;
ent - > client - > ps . pm_flags & = ~ PMF_FOLLOW ;
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
ent - > client - > ps . pm_type = PM_SPECTATOR ;
}
else
{
ent - > client - > ps . pm_type = PM_DEAD ;
ent - > health = ent - > client - > ps . stats [ STAT_HEALTH ] = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = =
G_StopFollowing
If the client being followed leaves the game , or you just want to drop
to free floating spectator mode
= = = = = = = = = = = = = = = = =
*/
void G_StopFollowing ( gentity_t * ent )
{
// Cant stop following if not following in the first place
if ( ! ( ent - > client - > ps . pm_flags & PMF_FOLLOW ) )
{
return ;
}
// Clear the following variables
ent - > client - > ps . pm_flags & = ~ PMF_FOLLOW ;
ent - > client - > sess . spectatorState = SPECTATOR_FREE ;
ent - > client - > ps . clientNum = ent - g_entities ;
ent - > client - > ps . zoomFov = 0 ;
2002-07-15 00:00:00 +00:00
ent - > client - > ps . loopSound = 0 ;
2002-05-24 00:00:00 +00:00
ent - > client - > ps . pm_flags & = ~ ( PMF_GOGGLES_ON | PMF_ZOOM_FLAGS ) ;
ent - > client - > ps . persistant [ PERS_TEAM ] = ent - > client - > sess . team ;
ent - > r . svFlags & = ~ SVF_BOT ;
// If we were in fact following someone, then make the angles and origin nice for
// when we stop
if ( ent - > client - > sess . spectatorClient ! = - 1 )
{
gclient_t * cl = & level . clients [ ent - > client - > sess . spectatorClient ] ;
int i ;
for ( i = 0 ; i < 3 ; i + + )
{
ent - > client - > ps . delta_angles [ i ] = ANGLE2SHORT ( cl - > ps . viewangles [ i ] - SHORT2ANGLE ( ent - > client - > pers . cmd . angles [ i ] ) ) ;
}
2002-09-24 00:00:00 +00:00
VectorCopy ( cl - > ps . viewangles , ent - > client - > ps . viewangles ) ;
2002-05-24 00:00:00 +00:00
VectorCopy ( cl - > ps . origin , ent - > client - > ps . origin ) ;
VectorClear ( ent - > client - > ps . velocity ) ;
ent - > client - > ps . movementDir = 0 ;
BG_PlayerStateToEntityState ( & ent - > client - > ps , & ent - > s , qtrue ) ;
}
2002-09-24 00:00:00 +00:00
// Ghots dont really become spectators, just psuedo spectators
if ( ent - > client - > sess . ghost )
{
// Do a start and stop to ensure the variables are all set properly
G_StopGhosting ( ent ) ;
G_StartGhosting ( ent ) ;
}
else
{
ent - > client - > sess . team = TEAM_SPECTATOR ;
ent - > client - > ps . persistant [ PERS_TEAM ] = TEAM_SPECTATOR ;
}
2002-05-24 00:00:00 +00:00
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Team_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Team_f ( gentity_t * ent )
{
char team [ MAX_TOKEN_CHARS ] ;
char identity [ MAX_TOKEN_CHARS ] ;
// Need at least the team specified in the arguments
if ( trap_Argc ( ) < 2 )
{
int oldTeam = ent - > client - > sess . team ;
switch ( oldTeam )
{
case TEAM_BLUE :
trap_SendServerCommand ( ent - g_entities , " print \" Blue team \n \" " ) ;
break ;
case TEAM_RED :
trap_SendServerCommand ( ent - g_entities , " print \" Red team \n \" " ) ;
break ;
case TEAM_FREE :
trap_SendServerCommand ( ent - g_entities , " print \" Free team \n \" " ) ;
break ;
case TEAM_SPECTATOR :
trap_SendServerCommand ( ent - g_entities , " print \" Spectator team \n \" " ) ;
break ;
}
return ;
}
// Limit how often one can switch team
if ( ent - > client - > switchTeamTime > level . time )
{
trap_SendServerCommand ( ent - g_entities , " print \" May not switch teams more than once per 5 seconds. \n \" " ) ;
return ;
}
trap_Argv ( 1 , team , sizeof ( team ) ) ;
trap_Argv ( 2 , identity , sizeof ( identity ) ) ;
SetTeam ( ent , team , identity [ 0 ] ? identity : NULL ) ;
// Remember the team switch time so they cant do it again really quick
ent - > client - > switchTeamTime = level . time + 5000 ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Follow_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Follow_f ( gentity_t * ent )
{
int i ;
char arg [ MAX_TOKEN_CHARS ] ;
if ( trap_Argc ( ) ! = 2 )
{
if ( ent - > client - > sess . spectatorState = = SPECTATOR_FOLLOW )
{
G_StopFollowing ( ent ) ;
}
return ;
}
trap_Argv ( 1 , arg , sizeof ( arg ) ) ;
i = ClientNumberFromString ( ent , arg ) ;
if ( i = = - 1 )
{
return ;
}
// can't follow self
if ( & level . clients [ i ] = = ent - > client )
{
return ;
}
// cant cycle to dead people
if ( level . clients [ i ] . ps . pm_type = = PM_DEAD )
{
return ;
}
// can't follow another spectator
if ( G_IsClientSpectating ( & level . clients [ i ] ) )
{
return ;
}
2002-07-15 00:00:00 +00:00
// Dissallow following of the enemy if the cvar is set
if ( level . gametypeData - > teams & & ! g_followEnemy . integer & & ent - > client - > sess . team ! = TEAM_SPECTATOR )
{
// Are they on the same team?
if ( level . clients [ i ] . sess . team ! = ent - > client - > sess . team )
{
return ;
}
}
2002-05-24 00:00:00 +00:00
// first set them to spectator as long as they arent a ghost
if ( ! ent - > client - > sess . ghost & & ent - > client - > sess . team ! = TEAM_SPECTATOR )
{
SetTeam ( ent , " spectator " , NULL ) ;
}
ent - > client - > sess . spectatorState = SPECTATOR_FOLLOW ;
ent - > client - > sess . spectatorClient = i ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_FollowCycle_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_FollowCycle_f ( gentity_t * ent , int dir )
{
int clientnum ;
int deadclient ;
int original ;
// first set them to spectator
if ( ! ent - > client - > sess . ghost & & ent - > client - > sess . team ! = TEAM_SPECTATOR )
{
SetTeam ( ent , " spectator " , NULL ) ;
}
if ( dir ! = 1 & & dir ! = - 1 )
{
Com_Error ( ERR_FATAL , " Cmd_FollowCycle_f: bad dir %i " , dir ) ;
}
if ( ent - > client - > sess . spectatorClient = = - 1 )
{
clientnum = original = ent - > s . number ;
}
else
{
clientnum = original = ent - > client - > sess . spectatorClient ;
}
deadclient = - 1 ;
do
{
clientnum + = dir ;
if ( clientnum > = level . maxclients )
{
clientnum = 0 ;
}
if ( clientnum < 0 )
{
clientnum = level . maxclients - 1 ;
}
// can only follow connected clients
if ( level . clients [ clientnum ] . pers . connected ! = CON_CONNECTED )
{
continue ;
}
// can't follow another spectator
if ( G_IsClientSpectating ( & level . clients [ clientnum ] ) )
{
continue ;
}
// Cant switch to dead people unless there is nobody else to switch to
if ( G_IsClientDead ( & level . clients [ clientnum ] ) )
{
deadclient = clientnum ;
continue ;
}
// Dissallow following of the enemy if the cvar is set
if ( level . gametypeData - > teams & & ! g_followEnemy . integer & & ent - > client - > sess . team ! = TEAM_SPECTATOR )
{
// Are they on the same team?
if ( level . clients [ clientnum ] . sess . team ! = ent - > client - > sess . team )
{
continue ;
}
}
// this is good, we can use it
ent - > client - > sess . spectatorClient = clientnum ;
ent - > client - > sess . spectatorState = SPECTATOR_FOLLOW ;
return ;
} while ( clientnum ! = original ) ;
// If being forced to follow and there is a dead client to jump to, then jump to them now
if ( deadclient ! = - 1 & & g_forceFollow . integer )
{
// this is good, we can use it
ent - > client - > sess . spectatorClient = deadclient ;
ent - > client - > sess . spectatorState = SPECTATOR_FOLLOW ;
return ;
}
G_StopFollowing ( ent ) ;
// leave it where it was
}
/*
= = = = = = = = = = = = = = = = = =
G_SayTo
= = = = = = = = = = = = = = = = = =
*/
static void G_SayTo ( gentity_t * ent , gentity_t * other , int mode , const char * name , const char * message )
{
qboolean ghost = qfalse ;
qboolean spec = qfalse ;
const char * type ;
if ( ! other )
{
return ;
}
if ( ! other - > inuse )
{
return ;
}
if ( ! other - > client )
{
return ;
}
if ( other - > client - > pers . connected ! = CON_CONNECTED )
{
return ;
}
if ( mode = = SAY_TEAM & & ! OnSameTeam ( ent , other ) )
{
return ;
}
2002-09-24 00:00:00 +00:00
if ( ent - > client - > sess . muted | | G_IsClientChatIgnored ( other - > s . number , ent - > s . number ) )
{
return ;
}
2002-05-24 00:00:00 +00:00
if ( ! level . intermissiontime & & ! level . intermissionQueued )
{
// Spectators cant talk to alive people
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
spec = qtrue ;
}
if ( level . gametypeData - > respawnType = = RT_NONE )
{
// Dead people cant talk to alive people
if ( ! spec & & G_IsClientDead ( ent - > client ) )
{
ghost = qtrue ;
}
// If the client we are talking to is alive then a check
// must be made to see if this talker is alowed to speak to this person
if ( ent - > s . number ! = other - > s . number & & ! G_IsClientDead ( other - > client ) & & ! G_IsClientSpectating ( other - > client ) & & ( ghost | | spec ) )
{
return ;
}
}
}
type = " " ;
if ( ghost )
{
type = " *ghost* " ;
}
else if ( spec )
{
type = " *spec* " ;
}
trap_SendServerCommand ( other - g_entities , va ( " %s %d \" %s%s%s \" " ,
mode = = SAY_TEAM ? " tchat " : " chat " ,
ent - > s . number ,
type , name , message ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
G_GetChatPrefix
= = = = = = = = = = = = = = = = = =
*/
void G_GetChatPrefix ( gentity_t * ent , gentity_t * target , int mode , char * name , int nameSize )
{
const char * namecolor ;
char location [ 64 ] ;
qboolean locationOk = qtrue ;
// Spectators and ghosts dont show locations
if ( ent - > client - > ps . pm_type = = PM_DEAD | | G_IsClientSpectating ( ent - > client ) )
{
locationOk = qfalse ;
}
if ( ! level . gametypeData - > teams & & mode = = SAY_TEAM )
{
mode = SAY_ALL ;
}
if ( level . gametypeData - > teams )
{
switch ( ent - > client - > sess . team )
{
case TEAM_BLUE :
namecolor = S_COLOR_BLUE ;
break ;
case TEAM_RED :
namecolor = S_COLOR_RED ;
break ;
default :
namecolor = S_COLOR_WHITE ;
break ;
}
}
else
{
namecolor = S_COLOR_WHITE ;
}
switch ( mode )
{
default :
case SAY_ALL :
Com_sprintf ( name , nameSize , " %s%s%s: " , namecolor , ent - > client - > pers . netname , S_COLOR_WHITE ) ;
break ;
case SAY_TEAM :
if ( locationOk & & Team_GetLocationMsg ( ent , location , sizeof ( location ) ) )
{
Com_sprintf ( name , nameSize , " %s(%s%s) %s(%s): " ,
namecolor ,
ent - > client - > pers . netname ,
namecolor ,
S_COLOR_WHITE , location ) ;
}
else
{
Com_sprintf ( name , nameSize , " %s(%s%s)%s: " ,
namecolor ,
ent - > client - > pers . netname ,
namecolor ,
S_COLOR_WHITE ) ;
}
break ;
case SAY_TELL :
if ( locationOk & & target & & level . gametypeData - > teams & &
target - > client - > sess . team = = ent - > client - > sess . team & &
Team_GetLocationMsg ( ent , location , sizeof ( location ) ) )
{
Com_sprintf ( name , nameSize , " %s[%s%s] %s(%s): " ,
namecolor ,
ent - > client - > pers . netname ,
namecolor ,
S_COLOR_WHITE , location ) ;
}
else
{
Com_sprintf ( name , nameSize , " %s[%s%s]%s: " ,
namecolor ,
ent - > client - > pers . netname ,
namecolor ,
S_COLOR_WHITE ) ;
}
break ;
}
strcat ( name , S_COLOR_GREEN ) ;
}
/*
= = = = = = = = = = = = = = = = = =
G_Say
= = = = = = = = = = = = = = = = = =
*/
void G_Say ( gentity_t * ent , gentity_t * target , int mode , const char * chatText )
{
int j ;
gentity_t * other ;
char text [ MAX_SAY_TEXT ] ;
2002-07-15 00:00:00 +00:00
char name [ 256 ] ;
2002-05-24 00:00:00 +00:00
// Logging stuff
switch ( mode )
{
case SAY_ALL :
G_LogPrintf ( " say: %s: %s \n " , ent - > client - > pers . netname , chatText ) ;
break ;
case SAY_TEAM :
G_LogPrintf ( " sayteam: %s: %s \n " , ent - > client - > pers . netname , chatText ) ;
break ;
}
// Generate the chat prefix
G_GetChatPrefix ( ent , target , mode , name , sizeof ( name ) ) ;
// Save off the chat text
Q_strncpyz ( text , chatText , sizeof ( text ) ) ;
if ( target )
{
G_SayTo ( ent , target , mode , name , text ) ;
return ;
}
// echo the text to the console
if ( g_dedicated . integer )
{
Com_Printf ( " %s%s \n " , name , text ) ;
}
// send it to all the apropriate clients
for ( j = 0 ; j < level . numConnectedClients ; j + + )
{
other = & g_entities [ level . sortedClients [ j ] ] ;
G_SayTo ( ent , other , mode , name , text ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Say_f
= = = = = = = = = = = = = = = = = =
*/
static void Cmd_Say_f ( gentity_t * ent , int mode , qboolean arg0 ) {
char * p ;
if ( trap_Argc ( ) < 2 & & ! arg0 ) {
return ;
}
if ( arg0 )
{
p = ConcatArgs ( 0 ) ;
}
else
{
p = ConcatArgs ( 1 ) ;
}
G_Say ( ent , NULL , mode , p ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Tell_f
= = = = = = = = = = = = = = = = = =
*/
static void Cmd_Tell_f ( gentity_t * ent ) {
int targetNum ;
gentity_t * target ;
char * p ;
char arg [ MAX_TOKEN_CHARS ] ;
if ( trap_Argc ( ) < 2 ) {
return ;
}
trap_Argv ( 1 , arg , sizeof ( arg ) ) ;
targetNum = atoi ( arg ) ;
if ( targetNum < 0 | | targetNum > = level . maxclients ) {
return ;
}
target = & g_entities [ targetNum ] ;
if ( ! target | | ! target - > inuse | | ! target - > client ) {
return ;
}
p = ConcatArgs ( 2 ) ;
G_LogPrintf ( " tell: %s to %s: %s \n " , ent - > client - > pers . netname , target - > client - > pers . netname , p ) ;
G_Say ( ent , target , SAY_TELL , p ) ;
// don't tell to the player self if it was already directed to this player
// also don't send the chat back to a bot
if ( ent ! = target & & ! ( ent - > r . svFlags & SVF_BOT ) ) {
G_Say ( ent , ent , SAY_TELL , p ) ;
}
}
static void G_VoiceTo ( gentity_t * ent , gentity_t * other , int mode , const char * name , const char * id , qboolean voiceonly )
{
// Only team say is supported right now for voice chatting
if ( mode ! = SAY_TEAM )
{
return ;
}
if ( ! other | | ! other - > inuse | | ! other - > client )
{
return ;
}
if ( ! OnSameTeam ( ent , other ) )
{
return ;
}
trap_SendServerCommand ( other - g_entities , va ( " %s %d %d \" %s \" \" %s \" " , " vtchat " , voiceonly , ent - > s . number , name , id ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
G_CanVoiceGlobal
Can we globaly speak right now
= = = = = = = = = = = = = = = = = =
*/
qboolean G_CanVoiceGlobal ( void )
{
if ( level . gametypeData - > teams & & level . time - level . globalVoiceTime > 5000 )
{
return qtrue ;
}
return qfalse ;
}
/*
= = = = = = = = = = = = = = = = = =
G_VoiceGlobal
says something out loud that everyone in the radius can hear
= = = = = = = = = = = = = = = = = =
*/
void G_VoiceGlobal ( gentity_t * ent , const char * id , qboolean force )
{
if ( ! ent )
{
return ;
}
if ( ! level . gametypeData - > teams )
{
return ;
}
if ( ! force & & level . time - level . globalVoiceTime < 5000 )
{
return ;
}
level . globalVoiceTime = level . time ;
trap_SendServerCommand ( - 1 , va ( " vglobal %d \" %s \" " , ent - > s . number , id ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
G_Voice
= = = = = = = = = = = = = = = = = =
*/
void G_Voice ( gentity_t * ent , gentity_t * target , int mode , const char * id , qboolean voiceonly )
{
int j ;
gentity_t * other ;
char name [ MAX_SAY_TEXT ] ;
// Spectators and ghosts dont talk
if ( ent - > client - > ps . pm_type = = PM_DEAD | | G_IsClientSpectating ( ent - > client ) )
{
return ;
}
// Voice flooding protection on?
if ( g_voiceFloodCount . integer )
{
// If this client has been penalized for voice chatting to much then dont allow the voice chat
if ( ent - > client - > voiceFloodPenalty )
{
if ( ent - > client - > voiceFloodPenalty > level . time )
{
return ;
}
// No longer penalized
ent - > client - > voiceFloodPenalty = 0 ;
}
// See if this client flooded with voice chats
ent - > client - > voiceFloodCount + + ;
if ( ent - > client - > voiceFloodCount > = g_voiceFloodCount . integer )
{
ent - > client - > voiceFloodCount = 0 ;
ent - > client - > voiceFloodTimer = 0 ;
ent - > client - > voiceFloodPenalty = level . time + g_voiceFloodPenalty . integer * 1000 ;
trap_SendServerCommand ( ent - g_entities , va ( " print \" Voice chat flooded, you will be able use voice chats again in (%d) seconds \n \" " , g_voiceFloodPenalty . integer ) ) ;
return ;
}
}
G_GetChatPrefix ( ent , target , mode , name , sizeof ( name ) ) ;
if ( target )
{
G_VoiceTo ( ent , target , mode , name , id , voiceonly ) ;
return ;
}
// send it to all the apropriate clients
for ( j = 0 ; j < level . maxclients ; j + + )
{
other = & g_entities [ j ] ;
G_VoiceTo ( ent , other , mode , name , id , voiceonly ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Voice_f
= = = = = = = = = = = = = = = = = =
*/
static void Cmd_Voice_f ( gentity_t * ent , int mode , qboolean arg0 , qboolean voiceonly )
{
char * p ;
if ( trap_Argc ( ) < 2 & & ! arg0 ) {
return ;
}
if ( arg0 )
{
p = ConcatArgs ( 0 ) ;
}
else
{
p = ConcatArgs ( 1 ) ;
}
G_Voice ( ent , NULL , mode , p , voiceonly ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Where_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Where_f ( gentity_t * ent )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , vtos ( ent - > s . origin ) ) ) ;
}
/*
= = = = = = = = = = = =
G_VoteDisabled
determins if the given vote is disabled
= = = = = = = = = = = =
*/
int G_VoteDisabled ( const char * callvote )
{
return trap_Cvar_VariableIntegerValue ( va ( " novote_%s " , callvote ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_CallVote_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_CallVote_f ( gentity_t * ent )
{
int i ;
char arg1 [ MAX_STRING_TOKENS ] ;
char arg2 [ MAX_STRING_TOKENS ] ;
if ( ! g_allowVote . integer )
{
trap_SendServerCommand ( ent - g_entities , " print \" Voting not allowed here. \n \" " ) ;
return ;
}
if ( level . intermissiontime | | level . intermissionQueued )
{
trap_SendServerCommand ( ent - g_entities , " print \" Voting not allowed during intermission. \n \" " ) ;
return ;
}
// No voting within the minute of a map change
if ( level . time - level . startTime < 1000 * 60 )
{
trap_SendServerCommand ( ent - g_entities , " print \" Cannot vote within the first minute of a map change. \n \" " ) ;
return ;
}
if ( level . numConnectedClients > 1 & & level . numVotingClients = = 1 )
{
trap_SendServerCommand ( ent - g_entities , " print \" You need at least 2 clients to call a vote. \n \" " ) ;
return ;
}
if ( level . voteTime )
{
trap_SendServerCommand ( ent - g_entities , " print \" A vote is already in progress. \n \" " ) ;
return ;
}
if ( ent - > client - > pers . voteCount > = MAX_VOTE_COUNT )
{
trap_SendServerCommand ( ent - g_entities , " print \" You have called the maximum number of votes. \n \" " ) ;
return ;
}
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
trap_SendServerCommand ( ent - g_entities , " print \" Not allowed to call a vote as spectator. \n \" " ) ;
return ;
}
if ( ent - > client - > voteDelayTime > level . time )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" You are not allowed to vote within %d minute of a failed vote. \n \" " , g_failedVoteDelay . integer ) ) ;
return ;
}
2002-09-24 00:00:00 +00:00
2002-05-24 00:00:00 +00:00
// Save the voting client id
level . voteClient = ent - > s . number ;
// make sure it is a valid command to vote on
trap_Argv ( 1 , arg1 , sizeof ( arg1 ) ) ;
trap_Argv ( 2 , arg2 , sizeof ( arg2 ) ) ;
if ( strchr ( arg1 , ' ; ' ) | | strchr ( arg2 , ' ; ' ) )
{
trap_SendServerCommand ( ent - g_entities , " print \" Invalid vote string. \n \" " ) ;
return ;
}
if ( ! Q_stricmp ( arg1 , " map_restart " ) ) {
} else if ( ! Q_stricmp ( arg1 , " mapcycle " ) ) {
} else if ( ! Q_stricmp ( arg1 , " map " ) ) {
} else if ( ! Q_stricmp ( arg1 , " rmgmap " ) ) {
} else if ( ! Q_stricmp ( arg1 , " g_gametype " ) ) {
} else if ( ! Q_stricmp ( arg1 , " kick " ) ) {
} else if ( ! Q_stricmp ( arg1 , " clientkick " ) ) {
} else if ( ! Q_stricmp ( arg1 , " g_doWarmup " ) ) {
2002-07-15 00:00:00 +00:00
} else if ( ! Q_stricmp ( arg1 , " g_friendlyfire " ) ) {
2002-05-24 00:00:00 +00:00
} else if ( ! Q_stricmp ( arg1 , " timelimit " ) ) {
} else if ( ! Q_stricmp ( arg1 , " timeextension " ) ) {
} else if ( ! Q_stricmp ( arg1 , " scorelimit " ) ) {
} else
{
trap_SendServerCommand ( ent - g_entities , " print \" Invalid vote string. \n \" " ) ;
trap_SendServerCommand ( ent - g_entities , " print \" Vote commands are: map_restart, nextmap, map <mapname>, g_gametype <n>, kick <player>, clientkick <clientnum>, g_doWarmup, timelimit <time>, scorelimit <score>. \n \" " ) ;
return ;
}
// see if this particular vote is disabled
if ( G_VoteDisabled ( arg1 ) )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" The '%s' vote has been disabled on this server. \n \" " , arg1 ) ) ;
return ;
}
// if there is still a vote to be executed
if ( level . voteExecuteTime )
{
level . voteExecuteTime = 0 ;
trap_SendConsoleCommand ( EXEC_APPEND , va ( " %s \n " , level . voteString ) ) ;
}
// special case for g_gametype, check for bad values
if ( ! Q_stricmp ( arg1 , " g_gametype " ) )
{
// Verify the gametype
i = BG_FindGametype ( arg2 ) ;
if ( i < 0 )
{
trap_SendServerCommand ( ent - g_entities , " print \" Invalid gametype. \n \" " ) ;
return ;
}
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s %s " , arg1 , arg2 ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s %s " , arg1 , bg_gametypeData [ i ] . name ) ;
}
else if ( ! Q_stricmp ( arg1 , " map " ) )
{
2002-09-24 00:00:00 +00:00
if ( ! G_DoesMapExist ( arg2 ) )
{
trap_SendServerCommand ( ent - g_entities , " print \" Unknown mapname. \n \" " ) ;
return ;
}
2002-05-24 00:00:00 +00:00
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s %s " , arg1 , arg2 ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s " , level . voteString ) ;
}
else if ( ! Q_stricmp ( arg1 , " rmgmap " ) )
{
char arg3 [ MAX_STRING_TOKENS ] ;
char arg4 [ MAX_STRING_TOKENS ] ;
trap_Argv ( 3 , arg3 , sizeof ( arg3 ) ) ;
trap_Argv ( 4 , arg4 , sizeof ( arg4 ) ) ;
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " rmgmap 1 %s 2 %s 3 %s 4 \" %s \" 0 " , arg2 , arg3 , arg4 , ConcatArgs ( 5 ) ) ;
2002-09-24 00:00:00 +00:00
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " Randomly Generated Map " ) ;
2002-05-24 00:00:00 +00:00
}
else if ( ! Q_stricmp ( arg1 , " mapcycle " ) )
{
if ( ! * g_mapcycle . string | | ! Q_stricmp ( g_mapcycle . string , " none " ) )
{
2002-07-15 00:00:00 +00:00
trap_SendServerCommand ( ent - g_entities , " print \" there is no map cycle currently set up. \n \" " ) ;
2002-05-24 00:00:00 +00:00
return ;
}
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " mapcycle " ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " nextmap " ) ;
}
else if ( ! Q_stricmp ( arg1 , " clientkick " ) )
{
int n = atoi ( arg2 ) ;
if ( n < 0 | | n > = MAX_CLIENTS )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" invalid client number %d. \n \" " , n ) ) ;
return ;
}
if ( g_entities [ n ] . client - > pers . connected = = CON_DISCONNECTED )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" there is no client with the client number %d. \n \" " , n ) ) ;
return ;
}
2002-07-15 00:00:00 +00:00
if ( g_voteKickBanTime . integer )
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " banclient %s %d voted off server " , arg2 , g_voteKickBanTime . integer ) ;
}
else
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " clientkick %s " , arg2 ) ;
}
2002-05-24 00:00:00 +00:00
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " kick %s " , g_entities [ n ] . client - > pers . netname ) ;
}
else if ( ! Q_stricmp ( arg1 , " kick " ) )
{
int clientid = G_ClientNumberFromName ( arg2 ) ;
if ( clientid = = - 1 )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" there is no client named '%s' currently on the server. \n \" " , arg2 ) ) ;
return ;
}
2002-07-15 00:00:00 +00:00
if ( g_voteKickBanTime . integer )
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " banclient %d %d voted off server " , clientid , g_voteKickBanTime . integer ) ;
}
else
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " clientkick %d " , clientid ) ;
}
2002-05-24 00:00:00 +00:00
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " kick %s " , g_entities [ clientid ] . client - > pers . netname ) ;
}
else if ( ! Q_stricmp ( arg1 , " timeextension " ) )
{
if ( ! g_timelimit . integer )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" There is no timelimit to extend. \n \" " ) ) ;
return ;
}
if ( ! g_timeextension . integer )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" This server does not allow time extensions. \n \" " ) ) ;
return ;
}
2002-09-24 00:00:00 +00:00
2002-05-24 00:00:00 +00:00
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " extendtime %d " , g_timeextension . integer ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " extend timelimit by %d minutes " , g_timeextension . integer ) ;
}
2002-09-24 00:00:00 +00:00
else if ( ! Q_stricmp ( arg1 , " timelimit " ) | |
! Q_stricmp ( arg1 , " scorelimit " ) | |
! Q_stricmp ( arg1 , " map_restart " ) | |
! Q_stricmp ( arg1 , " g_doWarmup " ) | |
! Q_stricmp ( arg1 , " g_friendlyfire " ) )
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s %d " , arg1 , atoi ( arg2 ) ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s " , level . voteString ) ;
}
2002-05-24 00:00:00 +00:00
else
{
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s \" %s \" " , arg1 , arg2 ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s " , level . voteString ) ;
}
trap_SendServerCommand ( - 1 , va ( " print \" %s called a vote. \n \" " , ent - > client - > pers . netname ) ) ;
// start the voting, the caller autoamtically votes yes
level . voteTime = level . time ;
level . voteYes = 1 ;
level . voteNo = 0 ;
for ( i = 0 ; i < level . maxclients ; i + + )
{
level . clients [ i ] . ps . eFlags & = ~ EF_VOTED ;
}
ent - > client - > ps . eFlags | = EF_VOTED ;
trap_SetConfigstring ( CS_VOTE_TIME , va ( " %i,%i " , level . voteTime , g_voteDuration . integer * 1000 ) ) ;
trap_SetConfigstring ( CS_VOTE_STRING , level . voteDisplayString ) ;
trap_SetConfigstring ( CS_VOTE_YES , va ( " %i " , level . voteYes ) ) ;
trap_SetConfigstring ( CS_VOTE_NO , va ( " %i " , level . voteNo ) ) ;
trap_SetConfigstring ( CS_VOTE_NEEDED , va ( " %i " , level . numVotingClients / 2 ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Vote_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Vote_f ( gentity_t * ent )
{
char msg [ 64 ] ;
if ( ! level . voteTime )
{
trap_SendServerCommand ( ent - g_entities , " print \" No vote in progress. \n \" " ) ;
return ;
}
if ( ent - > client - > ps . eFlags & EF_VOTED )
{
trap_SendServerCommand ( ent - g_entities , " print \" Vote already cast. \n \" " ) ;
return ;
}
if ( ent - > client - > sess . team = = TEAM_SPECTATOR )
{
trap_SendServerCommand ( ent - g_entities , " print \" Not allowed to vote as spectator. \n \" " ) ;
return ;
}
trap_SendServerCommand ( ent - g_entities , " print \" Vote cast. \n \" " ) ;
ent - > client - > ps . eFlags | = EF_VOTED ;
trap_Argv ( 1 , msg , sizeof ( msg ) ) ;
if ( msg [ 0 ] = = ' y ' | | msg [ 1 ] = = ' Y ' | | msg [ 1 ] = = ' 1 ' )
{
level . voteYes + + ;
trap_SetConfigstring ( CS_VOTE_YES , va ( " %i " , level . voteYes ) ) ;
}
else
{
level . voteNo + + ;
trap_SetConfigstring ( CS_VOTE_NO , va ( " %i " , level . voteNo ) ) ;
}
// a majority will be determined in CheckVote, which will also account
// for players entering or leaving
}
2002-09-24 00:00:00 +00:00
/*
= = = = = = = = = = = = = = = = =
Cmd_Ignore_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Ignore_f ( gentity_t * ent )
{
char buffer [ MAX_TOKEN_CHARS ] ;
int ignoree ;
qboolean ignore ;
trap_Argv ( 1 , buffer , sizeof ( buffer ) ) ;
ignoree = atoi ( buffer ) ;
ignore = G_IsClientChatIgnored ( ent - > s . number , ignoree ) ? qfalse : qtrue ;
if ( ignoree = = ent - > s . number )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" cant ignore yourself. \n \" " ) ) ;
return ;
}
G_IgnoreClientChat ( ent - > s . number , ignoree , ignore ) ;
if ( ignore )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s ignored. \n \" " , g_entities [ ignoree ] . client - > pers . netname ) ) ;
}
else
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s unignored. \n \" " , g_entities [ ignoree ] . client - > pers . netname ) ) ;
}
}
2002-05-24 00:00:00 +00:00
/*
= = = = = = = = = = = = = = = = =
Cmd_SetViewpos_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_SetViewpos_f ( gentity_t * ent )
{
vec3_t origin , angles ;
char buffer [ MAX_TOKEN_CHARS ] ;
int i ;
if ( ! g_cheats . integer )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" Cheats are not enabled on this server. \n \" " ) ) ;
return ;
}
if ( trap_Argc ( ) ! = 5 )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" usage: setviewpos x y z yaw \n \" " ) ) ;
return ;
}
VectorClear ( angles ) ;
for ( i = 0 ; i < 3 ; i + + )
{
trap_Argv ( i + 1 , buffer , sizeof ( buffer ) ) ;
origin [ i ] = atof ( buffer ) ;
}
trap_Argv ( 4 , buffer , sizeof ( buffer ) ) ;
angles [ YAW ] = atof ( buffer ) ;
TeleportPlayer ( ent , origin , angles ) ;
}
/*
= = = = = = = = = = = = = = = = =
ClientCommand
= = = = = = = = = = = = = = = = =
*/
void ClientCommand ( int clientNum ) {
gentity_t * ent ;
char cmd [ MAX_TOKEN_CHARS ] ;
ent = g_entities + clientNum ;
if ( ! ent - > client ) {
return ; // not fully in game yet
}
trap_Argv ( 0 , cmd , sizeof ( cmd ) ) ;
//rww - redirect bot commands
if ( strstr ( cmd , " bot_ " ) & & AcceptBotCommand ( cmd , ent ) )
{
return ;
}
//end rww
if ( Q_stricmp ( cmd , " say " ) = = 0 ) {
Cmd_Say_f ( ent , SAY_ALL , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " say_team " ) = = 0 ) {
Cmd_Say_f ( ent , SAY_TEAM , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " tell " ) = = 0 )
{
Cmd_Tell_f ( ent ) ;
return ;
}
if ( Q_stricmp ( cmd , " vsay_team " ) = = 0 )
{
Cmd_Voice_f ( ent , SAY_TEAM , qfalse , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " score " ) = = 0 ) {
Cmd_Score_f ( ent ) ;
return ;
}
if ( Q_stricmp ( cmd , " team " ) = = 0 )
{
Cmd_Team_f ( ent ) ;
return ;
}
// ignore all other commands when at intermission
if ( level . intermissiontime )
{
// Cmd_Say_f (ent, qfalse, qtrue);
return ;
}
if ( Q_stricmp ( cmd , " drop " ) = = 0 )
Cmd_Drop_f ( ent ) ;
2002-07-15 00:00:00 +00:00
else if ( Q_stricmp ( cmd , " dropitem " ) = = 0 )
Cmd_DropItem_f ( ent ) ;
2002-05-24 00:00:00 +00:00
else if ( Q_stricmp ( cmd , " give " ) = = 0 )
Cmd_Give_f ( ent ) ;
else if ( Q_stricmp ( cmd , " god " ) = = 0 )
Cmd_God_f ( ent ) ;
else if ( Q_stricmp ( cmd , " notarget " ) = = 0 )
Cmd_Notarget_f ( ent ) ;
else if ( Q_stricmp ( cmd , " noclip " ) = = 0 )
Cmd_Noclip_f ( ent ) ;
else if ( Q_stricmp ( cmd , " kill " ) = = 0 )
Cmd_Kill_f ( ent ) ;
else if ( Q_stricmp ( cmd , " levelshot " ) = = 0 )
Cmd_LevelShot_f ( ent ) ;
else if ( Q_stricmp ( cmd , " follow " ) = = 0 )
Cmd_Follow_f ( ent ) ;
else if ( Q_stricmp ( cmd , " follownext " ) = = 0 )
Cmd_FollowCycle_f ( ent , 1 ) ;
else if ( Q_stricmp ( cmd , " followprev " ) = = 0 )
Cmd_FollowCycle_f ( ent , - 1 ) ;
else if ( Q_stricmp ( cmd , " where " ) = = 0 )
Cmd_Where_f ( ent ) ;
else if ( Q_stricmp ( cmd , " callvote " ) = = 0 )
Cmd_CallVote_f ( ent ) ;
else if ( Q_stricmp ( cmd , " vote " ) = = 0 )
Cmd_Vote_f ( ent ) ;
else if ( Q_stricmp ( cmd , " setviewpos " ) = = 0 )
Cmd_SetViewpos_f ( ent ) ;
2002-09-24 00:00:00 +00:00
else if ( Q_stricmp ( cmd , " ignore " ) = = 0 )
Cmd_Ignore_f ( ent ) ;
2002-05-24 00:00:00 +00:00
# ifdef _SOF2_BOTS
else if ( Q_stricmp ( cmd , " addbot " ) = = 0 )
trap_SendServerCommand ( clientNum , va ( " print \" ADDBOT command can only be used via RCON \n \" " ) ) ;
# endif
else
trap_SendServerCommand ( clientNum , va ( " print \" unknown cmd %s \n \" " , cmd ) ) ;
}