2013-04-04 14:52:42 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
# include "g_local.h"
# include "../../ui/menudef.h" // for the voice chats
//rww - for getting bot commands...
int AcceptBotCommand ( char * cmd , gentity_t * pl ) ;
//end rww
void BG_CycleInven ( playerState_t * ps , int direction ) ;
void BG_CycleForce ( playerState_t * ps , int direction ) ;
/*
= = = = = = = = = = = = = = = = = =
DeathmatchScoreboardMessage
= = = = = = = = = = = = = = = = = =
*/
void DeathmatchScoreboardMessage ( gentity_t * ent ) {
char entry [ 1024 ] ;
char string [ 1400 ] ;
int stringlength ;
int i , j ;
gclient_t * cl ;
int numSorted , scoreFlags , accuracy , perfect ;
// send the latest information on all clients
string [ 0 ] = 0 ;
stringlength = 0 ;
scoreFlags = 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 ;
}
if ( cl - > accuracy_shots ) {
accuracy = cl - > accuracy_hits * 100 / cl - > accuracy_shots ;
}
else {
accuracy = 0 ;
}
perfect = ( cl - > ps . persistant [ PERS_RANK ] = = 0 & & cl - > ps . persistant [ PERS_KILLED ] = = 0 ) ? 1 : 0 ;
Com_sprintf ( entry , sizeof ( entry ) ,
" %i %i %i %i %i %i %i %i %i %i %i %i %i %i " , level . sortedClients [ i ] ,
cl - > ps . persistant [ PERS_SCORE ] , ping , ( level . time - cl - > pers . enterTime ) / 60000 ,
scoreFlags , g_entities [ level . sortedClients [ i ] ] . s . powerups , accuracy ,
cl - > ps . persistant [ PERS_IMPRESSIVE_COUNT ] ,
cl - > ps . persistant [ PERS_EXCELLENT_COUNT ] ,
cl - > ps . persistant [ PERS_GAUNTLET_FRAG_COUNT ] ,
cl - > ps . persistant [ PERS_DEFEND_COUNT ] ,
cl - > ps . persistant [ PERS_ASSIST_COUNT ] ,
perfect ,
cl - > ps . persistant [ PERS_CAPTURES ] ) ;
j = strlen ( entry ) ;
if ( stringlength + j > 1024 )
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 \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOCHEATS " ) ) ) ;
return qfalse ;
}
if ( ent - > health < = 0 ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " MUSTBEALIVE " ) ) ) ;
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 ;
}
/*
= = = = = = = = = = = = = = = = = =
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_Give_f
Give items to a client
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Give_f ( gentity_t * ent )
{
char name [ MAX_TOKEN_CHARS ] ;
gitem_t * it ;
int i ;
qboolean give_all ;
gentity_t * it_ent ;
trace_t trace ;
char arg [ MAX_TOKEN_CHARS ] ;
if ( ! CheatsOk ( ent ) ) {
return ;
}
trap_Argv ( 1 , name , sizeof ( name ) ) ;
if ( Q_stricmp ( name , " all " ) = = 0 )
give_all = qtrue ;
else
give_all = qfalse ;
if ( give_all | | Q_stricmp ( name , " health " ) = = 0 )
{
if ( trap_Argc ( ) = = 3 ) {
trap_Argv ( 2 , arg , sizeof ( arg ) ) ;
ent - > health = atoi ( arg ) ;
if ( ent - > health > ent - > client - > ps . stats [ STAT_MAX_HEALTH ] ) {
ent - > health = ent - > client - > ps . stats [ STAT_MAX_HEALTH ] ;
}
}
else {
ent - > health = ent - > client - > ps . stats [ STAT_MAX_HEALTH ] ;
}
if ( ! give_all )
return ;
}
if ( give_all | | Q_stricmp ( name , " weapons " ) = = 0 )
{
ent - > client - > ps . stats [ STAT_WEAPONS ] = ( 1 < < ( WP_DET_PACK + 1 ) ) - ( 1 < < WP_NONE ) ;
if ( ! give_all )
return ;
}
if ( ! give_all & & Q_stricmp ( name , " weaponnum " ) = = 0 )
{
trap_Argv ( 2 , arg , sizeof ( arg ) ) ;
ent - > client - > ps . stats [ STAT_WEAPONS ] | = ( 1 < < atoi ( arg ) ) ;
return ;
}
if ( give_all | | Q_stricmp ( name , " ammo " ) = = 0 )
{
int num = 999 ;
if ( trap_Argc ( ) = = 3 ) {
trap_Argv ( 2 , arg , sizeof ( arg ) ) ;
num = atoi ( arg ) ;
}
for ( i = 0 ; i < MAX_WEAPONS ; i + + ) {
ent - > client - > ps . ammo [ i ] = num ;
}
if ( ! give_all )
return ;
}
if ( give_all | | Q_stricmp ( name , " armor " ) = = 0 )
{
if ( trap_Argc ( ) = = 3 ) {
trap_Argv ( 2 , arg , sizeof ( arg ) ) ;
ent - > client - > ps . stats [ STAT_ARMOR ] = atoi ( arg ) ;
} else {
ent - > client - > ps . stats [ STAT_ARMOR ] = ent - > client - > ps . stats [ STAT_MAX_HEALTH ] ;
}
if ( ! give_all )
return ;
}
if ( Q_stricmp ( name , " excellent " ) = = 0 ) {
ent - > client - > ps . persistant [ PERS_EXCELLENT_COUNT ] + + ;
return ;
}
if ( Q_stricmp ( name , " impressive " ) = = 0 ) {
ent - > client - > ps . persistant [ PERS_IMPRESSIVE_COUNT ] + + ;
return ;
}
if ( Q_stricmp ( name , " gauntletaward " ) = = 0 ) {
ent - > client - > ps . persistant [ PERS_GAUNTLET_FRAG_COUNT ] + + ;
return ;
}
if ( Q_stricmp ( name , " defend " ) = = 0 ) {
ent - > client - > ps . persistant [ PERS_DEFEND_COUNT ] + + ;
return ;
}
if ( Q_stricmp ( name , " assist " ) = = 0 ) {
ent - > client - > ps . persistant [ PERS_ASSIST_COUNT ] + + ;
return ;
}
// spawn a specific item right on the player
if ( ! give_all ) {
it = BG_FindItem ( name ) ;
if ( ! it ) {
return ;
}
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 ;
}
// doesn't work in single player
if ( g_gametype . integer ! = 0 ) {
trap_SendServerCommand ( ent - g_entities ,
" print \" Must be in g_gametype 0 for levelshot \n \" " ) ;
return ;
}
BeginIntermission ( ) ;
trap_SendServerCommand ( ent - g_entities , " clientLevelShot " ) ;
}
/*
= = = = = = = = = = = = = = = = = =
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_TeamTask_f ( gentity_t * ent ) {
char userinfo [ MAX_INFO_STRING ] ;
char arg [ MAX_TOKEN_CHARS ] ;
int task ;
int client = ent - > client - level . clients ;
if ( trap_Argc ( ) ! = 2 ) {
return ;
}
trap_Argv ( 1 , arg , sizeof ( arg ) ) ;
task = atoi ( arg ) ;
trap_GetUserinfo ( client , userinfo , sizeof ( userinfo ) ) ;
Info_SetValueForKey ( userinfo , " teamtask " , va ( " %d " , task ) ) ;
trap_SetUserinfo ( client , userinfo ) ;
ClientUserinfoChanged ( client ) ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Kill_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Kill_f ( gentity_t * ent ) {
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR ) {
return ;
}
if ( ent - > health < = 0 ) {
return ;
}
if ( g_gametype . integer = = GT_TOURNAMENT & & level . numPlayingClients > 1 & & ! level . warmupTime )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " ATTEMPTDUELKILL " ) ) ) ;
return ;
}
ent - > flags & = ~ FL_GODMODE ;
ent - > client - > ps . stats [ STAT_HEALTH ] = ent - > health = - 999 ;
player_die ( ent , ent , ent , 100000 , MOD_SUICIDE ) ;
}
gentity_t * G_GetDuelWinner ( gclient_t * client )
{
gclient_t * wCl ;
int i ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
wCl = & level . clients [ i ] ;
if ( wCl & & wCl ! = client & & /*wCl->ps.clientNum != client->ps.clientNum &&*/
wCl - > pers . connected = = CON_CONNECTED & & wCl - > sess . sessionTeam ! = TEAM_SPECTATOR )
{
return & g_entities [ wCl - > ps . clientNum ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = =
BroadCastTeamChange
Let everyone know about a team change
= = = = = = = = = = = = = = = = =
*/
void BroadcastTeamChange ( gclient_t * client , int oldTeam )
{
client - > ps . fd . forceDoInit = 1 ; //every time we change teams make sure our force powers are set right
if ( client - > sess . sessionTeam = = TEAM_RED ) {
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s \n \" " ,
client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " JOINEDTHEREDTEAM " ) ) ) ;
} else if ( client - > sess . sessionTeam = = TEAM_BLUE ) {
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s \n \" " ,
client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " JOINEDTHEBLUETEAM " ) ) ) ;
} else if ( client - > sess . sessionTeam = = TEAM_SPECTATOR & & oldTeam ! = TEAM_SPECTATOR ) {
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s \n \" " ,
client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " JOINEDTHESPECTATORS " ) ) ) ;
} else if ( client - > sess . sessionTeam = = TEAM_FREE ) {
if ( g_gametype . integer = = GT_TOURNAMENT )
{
/*
gentity_t * currentWinner = G_GetDuelWinner ( client ) ;
if ( currentWinner & & currentWinner - > client )
{
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s %s \n \" " ,
currentWinner - > client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " VERSUS " ) , client - > pers . netname ) ) ;
}
else
{
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s \n \" " ,
client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " JOINEDTHEBATTLE " ) ) ) ;
}
*/
//NOTE: Just doing a vs. once it counts two players up
}
else
{
trap_SendServerCommand ( - 1 , va ( " cp \" %s " S_COLOR_WHITE " %s \n \" " ,
client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " JOINEDTHEBATTLE " ) ) ) ;
}
}
2013-04-04 18:01:17 +00:00
G_LogPrintf ( " setteam: %i %s %s \n " ,
client - & level . clients [ 0 ] ,
TeamName ( oldTeam ) ,
TeamName ( client - > sess . sessionTeam ) ) ;
2013-04-04 14:52:42 +00:00
}
/*
= = = = = = = = = = = = = = = = =
SetTeam
= = = = = = = = = = = = = = = = =
*/
void SetTeam ( gentity_t * ent , char * s ) {
int team , oldTeam ;
gclient_t * client ;
int clientNum ;
spectatorState_t specState ;
int specClient ;
int teamLeader ;
//
// see what change is requested
//
client = ent - > client ;
clientNum = client - level . clients ;
specClient = 0 ;
specState = SPECTATOR_NOT ;
if ( ! Q_stricmp ( s , " scoreboard " ) | | ! Q_stricmp ( s , " score " ) ) {
team = TEAM_SPECTATOR ;
specState = SPECTATOR_SCOREBOARD ;
} else 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 ( g_gametype . integer > = GT_TEAM ) {
// 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
if ( g_forceBasedTeams . integer )
{
if ( ent - > client - > ps . fd . forceSide = = FORCE_LIGHTSIDE )
{
team = TEAM_BLUE ;
}
else
{
team = TEAM_RED ;
}
}
else
{
team = PickTeam ( clientNum ) ;
}
}
if ( g_teamForceBalance . integer ) {
int counts [ TEAM_NUM_TEAMS ] ;
counts [ TEAM_BLUE ] = TeamCount ( ent - > client - > ps . clientNum , TEAM_BLUE ) ;
counts [ TEAM_RED ] = TeamCount ( ent - > client - > ps . clientNum , TEAM_RED ) ;
// We allow a spread of two
if ( team = = TEAM_RED & & counts [ TEAM_RED ] - counts [ TEAM_BLUE ] > 1 ) {
if ( g_forceBasedTeams . integer & & ent - > client - > ps . fd . forceSide = = FORCE_DARKSIDE )
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TOOMANYRED_SWITCH " ) ) ) ;
}
else
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TOOMANYRED " ) ) ) ;
}
return ; // ignore the request
}
if ( team = = TEAM_BLUE & & counts [ TEAM_BLUE ] - counts [ TEAM_RED ] > 1 ) {
if ( g_forceBasedTeams . integer & & ent - > client - > ps . fd . forceSide = = FORCE_LIGHTSIDE )
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TOOMANYBLUE_SWITCH " ) ) ) ;
}
else
{
trap_SendServerCommand ( ent - > client - > ps . clientNum ,
va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TOOMANYBLUE " ) ) ) ;
}
return ; // ignore the request
}
// It's ok, the team we are switching to has less or same number of players
}
if ( g_forceBasedTeams . integer )
{
if ( team = = TEAM_BLUE & & ent - > client - > ps . fd . forceSide ! = FORCE_LIGHTSIDE )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " MUSTBELIGHT " ) ) ) ;
return ;
}
if ( team = = TEAM_RED & & ent - > client - > ps . fd . forceSide ! = FORCE_DARKSIDE )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " MUSTBEDARK " ) ) ) ;
return ;
}
}
} else {
// force them to spectators if there aren't any spots free
team = TEAM_FREE ;
}
// override decision if limiting the players
if ( ( g_gametype . integer = = GT_TOURNAMENT )
& & level . numNonSpectatorClients > = 2 ) {
team = TEAM_SPECTATOR ;
} else if ( g_maxGameClients . integer > 0 & &
level . numNonSpectatorClients > = g_maxGameClients . integer ) {
team = TEAM_SPECTATOR ;
}
//
// decide if we will allow the change
//
oldTeam = client - > sess . sessionTeam ;
if ( team = = oldTeam & & team ! = TEAM_SPECTATOR ) {
return ;
}
//
// execute the team change
//
// if the player was dead leave the body
if ( client - > ps . stats [ STAT_HEALTH ] < = 0 ) {
CopyToBodyQue ( ent ) ;
}
// he starts at 'base'
client - > pers . teamState . state = TEAM_BEGIN ;
if ( oldTeam ! = TEAM_SPECTATOR ) {
// 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_SUICIDE ) ;
}
// they go to the end of the line for tournements
if ( team = = TEAM_SPECTATOR ) {
client - > sess . spectatorTime = level . time ;
}
client - > sess . sessionTeam = team ;
client - > sess . spectatorState = specState ;
client - > sess . spectatorClient = specClient ;
client - > sess . teamLeader = qfalse ;
if ( team = = TEAM_RED | | team = = TEAM_BLUE ) {
teamLeader = TeamLeader ( team ) ;
// if there is no team leader or the team leader is a bot and this client is not a bot
if ( teamLeader = = - 1 | | ( ! ( g_entities [ clientNum ] . r . svFlags & SVF_BOT ) & & ( g_entities [ teamLeader ] . r . svFlags & SVF_BOT ) ) ) {
SetLeader ( team , clientNum ) ;
}
}
// make sure there is a team leader on the team the player came from
if ( oldTeam = = TEAM_RED | | oldTeam = = TEAM_BLUE ) {
CheckTeamLeader ( oldTeam ) ;
}
BroadcastTeamChange ( client , oldTeam ) ;
// get and distribute relevent paramters
ClientUserinfoChanged ( clientNum ) ;
ClientBegin ( clientNum ) ;
}
/*
= = = = = = = = = = = = = = = = =
StopFollowing
If the client being followed leaves the game , or you just want to drop
to free floating spectator mode
= = = = = = = = = = = = = = = = =
*/
void StopFollowing ( gentity_t * ent ) {
ent - > client - > ps . persistant [ PERS_TEAM ] = TEAM_SPECTATOR ;
ent - > client - > sess . sessionTeam = TEAM_SPECTATOR ;
ent - > client - > sess . spectatorState = SPECTATOR_FREE ;
ent - > client - > ps . pm_flags & = ~ PMF_FOLLOW ;
ent - > r . svFlags & = ~ SVF_BOT ;
ent - > client - > ps . clientNum = ent - g_entities ;
ent - > client - > ps . weapon = WP_NONE ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Team_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Team_f ( gentity_t * ent ) {
int oldTeam ;
char s [ MAX_TOKEN_CHARS ] ;
if ( trap_Argc ( ) ! = 2 ) {
oldTeam = ent - > client - > sess . sessionTeam ;
switch ( oldTeam ) {
case TEAM_BLUE :
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " PRINTBLUETEAM " ) ) ) ;
break ;
case TEAM_RED :
trap_SendServerCommand ( ent - g_entities , va ( " print \" Red team \n \" " , G_GetStripEdString ( " SVINGAME " , " PRINTREDTEAM " ) ) ) ;
break ;
case TEAM_FREE :
trap_SendServerCommand ( ent - g_entities , va ( " print \" Free team \n \" " , G_GetStripEdString ( " SVINGAME " , " PRINTFREETEAM " ) ) ) ;
break ;
case TEAM_SPECTATOR :
trap_SendServerCommand ( ent - g_entities , va ( " print \" Spectator team \n \" " , G_GetStripEdString ( " SVINGAME " , " PRINTSPECTEAM " ) ) ) ;
break ;
}
return ;
}
if ( ent - > client - > switchTeamTime > level . time ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOSWITCH " ) ) ) ;
return ;
}
// if they are playing a tournement game, count as a loss
if ( ( g_gametype . integer = = GT_TOURNAMENT )
& & ent - > client - > sess . sessionTeam = = TEAM_FREE ) {
ent - > client - > sess . losses + + ;
}
trap_Argv ( 1 , s , sizeof ( s ) ) ;
SetTeam ( ent , s ) ;
ent - > client - > switchTeamTime = level . time + 5000 ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Team_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_ForceChanged_f ( gentity_t * ent )
{
// Cmd_Kill_f(ent);
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR )
{ //if it's a spec, just make the changes now
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " FORCEAPPLIED " ) ) ) ;
WP_InitForcePowers ( ent ) ;
return ;
}
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " FORCEPOWERCHANGED " ) ) ) ;
ent - > client - > ps . fd . forceDoInit = 1 ;
}
/*
= = = = = = = = = = = = = = = = =
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 ) {
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 ;
}
// can't follow another spectator
if ( level . clients [ i ] . sess . sessionTeam = = TEAM_SPECTATOR ) {
return ;
}
// if they are playing a tournement game, count as a loss
if ( ( g_gametype . integer = = GT_TOURNAMENT )
& & ent - > client - > sess . sessionTeam = = TEAM_FREE ) {
ent - > client - > sess . losses + + ;
}
// first set them to spectator
if ( ent - > client - > sess . sessionTeam ! = TEAM_SPECTATOR ) {
SetTeam ( ent , " spectator " ) ;
}
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 original ;
// if they are playing a tournement game, count as a loss
if ( ( g_gametype . integer = = GT_TOURNAMENT )
& & ent - > client - > sess . sessionTeam = = TEAM_FREE ) {
ent - > client - > sess . losses + + ;
}
// first set them to spectator
if ( ent - > client - > sess . spectatorState = = SPECTATOR_NOT ) {
SetTeam ( ent , " spectator " ) ;
}
if ( dir ! = 1 & & dir ! = - 1 ) {
G_Error ( " Cmd_FollowCycle_f: bad dir %i " , dir ) ;
}
clientnum = ent - > client - > sess . spectatorClient ;
original = clientnum ;
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 ( level . clients [ clientnum ] . sess . sessionTeam = = TEAM_SPECTATOR ) {
continue ;
}
// this is good, we can use it
ent - > client - > sess . spectatorClient = clientnum ;
ent - > client - > sess . spectatorState = SPECTATOR_FOLLOW ;
return ;
} while ( clientnum ! = original ) ;
// leave it where it was
}
/*
= = = = = = = = = = = = = = = = = =
G_Say
= = = = = = = = = = = = = = = = = =
*/
static void G_SayTo ( gentity_t * ent , gentity_t * other , int mode , int color , const char * name , const char * message ) {
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 ;
}
// no chatting to players in tournements
if ( ( g_gametype . integer = = GT_TOURNAMENT )
& & other - > client - > sess . sessionTeam = = TEAM_FREE
& & ent - > client - > sess . sessionTeam ! = TEAM_FREE ) {
return ;
}
trap_SendServerCommand ( other - g_entities , va ( " %s \" %s%c%c%s \" " ,
mode = = SAY_TEAM ? " tchat " : " chat " ,
name , Q_COLOR_ESCAPE , color , message ) ) ;
}
# define EC "\x19"
void G_Say ( gentity_t * ent , gentity_t * target , int mode , const char * chatText ) {
int j ;
gentity_t * other ;
int color ;
char name [ 64 ] ;
// don't let text be too long for malicious reasons
char text [ MAX_SAY_TEXT ] ;
char location [ 64 ] ;
if ( g_gametype . integer < GT_TEAM & & mode = = SAY_TEAM ) {
mode = SAY_ALL ;
}
switch ( mode ) {
default :
case SAY_ALL :
G_LogPrintf ( " say: %s: %s \n " , ent - > client - > pers . netname , chatText ) ;
Com_sprintf ( name , sizeof ( name ) , " %s%c%c " EC " : " , ent - > client - > pers . netname , Q_COLOR_ESCAPE , COLOR_WHITE ) ;
color = COLOR_GREEN ;
break ;
case SAY_TEAM :
G_LogPrintf ( " sayteam: %s: %s \n " , ent - > client - > pers . netname , chatText ) ;
if ( Team_GetLocationMsg ( ent , location , sizeof ( location ) ) )
Com_sprintf ( name , sizeof ( name ) , EC " (%s%c%c " EC " ) (%s) " EC " : " ,
ent - > client - > pers . netname , Q_COLOR_ESCAPE , COLOR_WHITE , location ) ;
else
Com_sprintf ( name , sizeof ( name ) , EC " (%s%c%c " EC " ) " EC " : " ,
ent - > client - > pers . netname , Q_COLOR_ESCAPE , COLOR_WHITE ) ;
color = COLOR_CYAN ;
break ;
case SAY_TELL :
if ( target & & g_gametype . integer > = GT_TEAM & &
target - > client - > sess . sessionTeam = = ent - > client - > sess . sessionTeam & &
Team_GetLocationMsg ( ent , location , sizeof ( location ) ) )
Com_sprintf ( name , sizeof ( name ) , EC " [%s%c%c " EC " ] (%s) " EC " : " , ent - > client - > pers . netname , Q_COLOR_ESCAPE , COLOR_WHITE , location ) ;
else
Com_sprintf ( name , sizeof ( name ) , EC " [%s%c%c " EC " ] " EC " : " , ent - > client - > pers . netname , Q_COLOR_ESCAPE , COLOR_WHITE ) ;
color = COLOR_MAGENTA ;
break ;
}
Q_strncpyz ( text , chatText , sizeof ( text ) ) ;
if ( target ) {
G_SayTo ( ent , target , mode , color , name , text ) ;
return ;
}
// echo the text to the console
if ( g_dedicated . integer ) {
G_Printf ( " %s%s \n " , name , text ) ;
}
// send it to all the apropriate clients
for ( j = 0 ; j < level . maxclients ; j + + ) {
other = & g_entities [ j ] ;
G_SayTo ( ent , other , mode , color , 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 * id , qboolean voiceonly ) {
int color ;
char * cmd ;
if ( ! other ) {
return ;
}
if ( ! other - > inuse ) {
return ;
}
if ( ! other - > client ) {
return ;
}
if ( mode = = SAY_TEAM & & ! OnSameTeam ( ent , other ) ) {
return ;
}
// no chatting to players in tournements
if ( ( g_gametype . integer = = GT_TOURNAMENT ) ) {
return ;
}
if ( mode = = SAY_TEAM ) {
color = COLOR_CYAN ;
cmd = " vtchat " ;
}
else if ( mode = = SAY_TELL ) {
color = COLOR_MAGENTA ;
cmd = " vtell " ;
}
else {
color = COLOR_GREEN ;
cmd = " vchat " ;
}
trap_SendServerCommand ( other - g_entities , va ( " %s %d %d %d %s " , cmd , voiceonly , ent - > s . number , color , id ) ) ;
}
void G_Voice ( gentity_t * ent , gentity_t * target , int mode , const char * id , qboolean voiceonly ) {
int j ;
gentity_t * other ;
if ( g_gametype . integer < GT_TEAM & & mode = = SAY_TEAM ) {
mode = SAY_ALL ;
}
if ( target ) {
G_VoiceTo ( ent , target , mode , id , voiceonly ) ;
return ;
}
// echo the text to the console
if ( g_dedicated . integer ) {
G_Printf ( " voice: %s %s \n " , ent - > client - > pers . netname , id ) ;
}
// send it to all the apropriate clients
for ( j = 0 ; j < level . maxclients ; j + + ) {
other = & g_entities [ j ] ;
G_VoiceTo ( ent , other , mode , 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_VoiceTell_f
= = = = = = = = = = = = = = = = = =
*/
static void Cmd_VoiceTell_f ( gentity_t * ent , qboolean voiceonly ) {
int targetNum ;
gentity_t * target ;
char * id ;
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 ;
}
id = ConcatArgs ( 2 ) ;
G_LogPrintf ( " vtell: %s to %s: %s \n " , ent - > client - > pers . netname , target - > client - > pers . netname , id ) ;
G_Voice ( ent , target , SAY_TELL , id , voiceonly ) ;
// 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_Voice ( ent , ent , SAY_TELL , id , voiceonly ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_VoiceTaunt_f
= = = = = = = = = = = = = = = = = =
*/
static void Cmd_VoiceTaunt_f ( gentity_t * ent ) {
gentity_t * who ;
int i ;
if ( ! ent - > client ) {
return ;
}
// insult someone who just killed you
if ( ent - > enemy & & ent - > enemy - > client & & ent - > enemy - > client - > lastkilled_client = = ent - > s . number ) {
// i am a dead corpse
if ( ! ( ent - > enemy - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , ent - > enemy , SAY_TELL , VOICECHAT_DEATHINSULT , qfalse ) ;
}
if ( ! ( ent - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , ent , SAY_TELL , VOICECHAT_DEATHINSULT , qfalse ) ;
}
ent - > enemy = NULL ;
return ;
}
// insult someone you just killed
if ( ent - > client - > lastkilled_client > = 0 & & ent - > client - > lastkilled_client ! = ent - > s . number ) {
who = g_entities + ent - > client - > lastkilled_client ;
if ( who - > client ) {
// who is the person I just killed
if ( who - > client - > lasthurt_mod = = MOD_STUN_BATON ) {
if ( ! ( who - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , who , SAY_TELL , VOICECHAT_KILLGAUNTLET , qfalse ) ; // and I killed them with a gauntlet
}
if ( ! ( ent - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , ent , SAY_TELL , VOICECHAT_KILLGAUNTLET , qfalse ) ;
}
} else {
if ( ! ( who - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , who , SAY_TELL , VOICECHAT_KILLINSULT , qfalse ) ; // and I killed them with something else
}
if ( ! ( ent - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , ent , SAY_TELL , VOICECHAT_KILLINSULT , qfalse ) ;
}
}
ent - > client - > lastkilled_client = - 1 ;
return ;
}
}
if ( g_gametype . integer > = GT_TEAM ) {
// praise a team mate who just got a reward
for ( i = 0 ; i < MAX_CLIENTS ; i + + ) {
who = g_entities + i ;
if ( who - > client & & who ! = ent & & who - > client - > sess . sessionTeam = = ent - > client - > sess . sessionTeam ) {
if ( who - > client - > rewardTime > level . time ) {
if ( ! ( who - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , who , SAY_TELL , VOICECHAT_PRAISE , qfalse ) ;
}
if ( ! ( ent - > r . svFlags & SVF_BOT ) ) {
G_Voice ( ent , ent , SAY_TELL , VOICECHAT_PRAISE , qfalse ) ;
}
return ;
}
}
}
}
// just say something
G_Voice ( ent , NULL , SAY_ALL , VOICECHAT_TAUNT , qfalse ) ;
}
static char * gc_orders [ ] = {
" hold your position " ,
" hold this position " ,
" come here " ,
" cover me " ,
" guard location " ,
" search and destroy " ,
" report "
} ;
void Cmd_GameCommand_f ( gentity_t * ent ) {
int player ;
int order ;
char str [ MAX_TOKEN_CHARS ] ;
trap_Argv ( 1 , str , sizeof ( str ) ) ;
player = atoi ( str ) ;
trap_Argv ( 2 , str , sizeof ( str ) ) ;
order = atoi ( str ) ;
if ( player < 0 | | player > = MAX_CLIENTS ) {
return ;
}
if ( order < 0 | | order > sizeof ( gc_orders ) / sizeof ( char * ) ) {
return ;
}
G_Say ( ent , & g_entities [ player ] , SAY_TELL , gc_orders [ order ] ) ;
G_Say ( ent , ent , SAY_TELL , gc_orders [ order ] ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Where_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Where_f ( gentity_t * ent ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , vtos ( ent - > s . origin ) ) ) ;
}
static const char * gameNames [ ] = {
" Free For All " ,
" Holocron FFA " ,
" Jedi Master " ,
" Duel " ,
" Single Player " ,
" Team FFA " ,
" Saga " ,
" Capture the Flag "
} ;
/*
= = = = = = = = = = = = = = = = = =
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 , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOVOTE " ) ) ) ;
return ;
}
if ( level . voteTime ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " VOTEINPROGRESS " ) ) ) ;
return ;
}
if ( ent - > client - > pers . voteCount > = MAX_VOTE_COUNT ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " MAXVOTES " ) ) ) ;
return ;
}
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOSPECVOTE " ) ) ) ;
return ;
}
// 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 , " nextmap " ) ) {
} else if ( ! Q_stricmp ( arg1 , " map " ) ) {
} 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 " ) ) {
} else if ( ! Q_stricmp ( arg1 , " timelimit " ) ) {
} else if ( ! Q_stricmp ( arg1 , " fraglimit " ) ) {
} 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>, fraglimit <frags>. \n \" " ) ;
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 " ) ) {
i = atoi ( arg2 ) ;
if ( i = = GT_SINGLE_PLAYER | | i < GT_FFA | | i > = GT_MAX_GAME_TYPE ) {
trap_SendServerCommand ( ent - g_entities , " print \" Invalid gametype. \n \" " ) ;
return ;
}
level . votingGametype = qtrue ;
level . votingGametypeTo = i ;
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s %d " , arg1 , i ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s %s " , arg1 , gameNames [ i ] ) ;
} else if ( ! Q_stricmp ( arg1 , " map " ) ) {
// special case for map changes, we want to reset the nextmap setting
// this allows a player to change maps, but not upset the map rotation
char s [ MAX_STRING_CHARS ] ;
trap_Cvar_VariableStringBuffer ( " nextmap " , s , sizeof ( s ) ) ;
if ( * s ) {
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " %s %s; set nextmap \" %s \" " , arg1 , arg2 , s ) ;
} else {
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 , " nextmap " ) ) {
char s [ MAX_STRING_CHARS ] ;
trap_Cvar_VariableStringBuffer ( " nextmap " , s , sizeof ( s ) ) ;
if ( ! * s ) {
trap_SendServerCommand ( ent - g_entities , " print \" nextmap not set. \n \" " ) ;
return ;
}
Com_sprintf ( level . voteString , sizeof ( level . voteString ) , " vstr nextmap " ) ;
Com_sprintf ( level . voteDisplayString , sizeof ( level . voteDisplayString ) , " %s " , level . voteString ) ;
} 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 %s \n \" " , ent - > client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " PLCALLEDVOTE " ) ) ) ;
// 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 " , level . voteTime ) ) ;
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 ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Vote_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Vote_f ( gentity_t * ent ) {
char msg [ 64 ] ;
if ( ! level . voteTime ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOVOTEINPROG " ) ) ) ;
return ;
}
if ( ent - > client - > ps . eFlags & EF_VOTED ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " VOTEALREADY " ) ) ) ;
return ;
}
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOVOTEASSPEC " ) ) ) ;
return ;
}
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " PLVOTECAST " ) ) ) ;
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
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_CallTeamVote_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_CallTeamVote_f ( gentity_t * ent ) {
int i , team , cs_offset ;
char arg1 [ MAX_STRING_TOKENS ] ;
char arg2 [ MAX_STRING_TOKENS ] ;
team = ent - > client - > sess . sessionTeam ;
if ( team = = TEAM_RED )
cs_offset = 0 ;
else if ( team = = TEAM_BLUE )
cs_offset = 1 ;
else
return ;
if ( ! g_allowVote . integer ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOVOTE " ) ) ) ;
return ;
}
if ( level . teamVoteTime [ cs_offset ] ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TEAMVOTEALREADY " ) ) ) ;
return ;
}
if ( ent - > client - > pers . teamVoteCount > = MAX_VOTE_COUNT ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " MAXTEAMVOTES " ) ) ) ;
return ;
}
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOSPECVOTE " ) ) ) ;
return ;
}
// make sure it is a valid command to vote on
trap_Argv ( 1 , arg1 , sizeof ( arg1 ) ) ;
arg2 [ 0 ] = ' \0 ' ;
for ( i = 2 ; i < trap_Argc ( ) ; i + + ) {
if ( i > 2 )
strcat ( arg2 , " " ) ;
trap_Argv ( i , & arg2 [ strlen ( arg2 ) ] , sizeof ( arg2 ) - strlen ( arg2 ) ) ;
}
if ( strchr ( arg1 , ' ; ' ) | | strchr ( arg2 , ' ; ' ) ) {
trap_SendServerCommand ( ent - g_entities , " print \" Invalid vote string. \n \" " ) ;
return ;
}
if ( ! Q_stricmp ( arg1 , " leader " ) ) {
char netname [ MAX_NETNAME ] , leader [ MAX_NETNAME ] ;
if ( ! arg2 [ 0 ] ) {
i = ent - > client - > ps . clientNum ;
}
else {
// numeric values are just slot numbers
for ( i = 0 ; i < 3 ; i + + ) {
if ( ! arg2 [ i ] | | arg2 [ i ] < ' 0 ' | | arg2 [ i ] > ' 9 ' )
break ;
}
if ( i > = 3 | | ! arg2 [ i ] ) {
i = atoi ( arg2 ) ;
if ( i < 0 | | i > = level . maxclients ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" Bad client slot: %i \n \" " , i ) ) ;
return ;
}
if ( ! g_entities [ i ] . inuse ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" Client %i is not active \n \" " , i ) ) ;
return ;
}
}
else {
Q_strncpyz ( leader , arg2 , sizeof ( leader ) ) ;
Q_CleanStr ( leader ) ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
if ( level . clients [ i ] . pers . connected = = CON_DISCONNECTED )
continue ;
if ( level . clients [ i ] . sess . sessionTeam ! = team )
continue ;
Q_strncpyz ( netname , level . clients [ i ] . pers . netname , sizeof ( netname ) ) ;
Q_CleanStr ( netname ) ;
if ( ! Q_stricmp ( netname , leader ) ) {
break ;
}
}
if ( i > = level . maxclients ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s is not a valid player on your team. \n \" " , arg2 ) ) ;
return ;
}
}
}
Com_sprintf ( arg2 , sizeof ( arg2 ) , " %d " , i ) ;
} else {
trap_SendServerCommand ( ent - g_entities , " print \" Invalid vote string. \n \" " ) ;
trap_SendServerCommand ( ent - g_entities , " print \" Team vote commands are: leader <player>. \n \" " ) ;
return ;
}
Com_sprintf ( level . teamVoteString [ cs_offset ] , sizeof ( level . teamVoteString [ cs_offset ] ) , " %s %s " , arg1 , arg2 ) ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
if ( level . clients [ i ] . pers . connected = = CON_DISCONNECTED )
continue ;
if ( level . clients [ i ] . sess . sessionTeam = = team )
trap_SendServerCommand ( i , va ( " print \" %s called a team vote. \n \" " , ent - > client - > pers . netname ) ) ;
}
// start the voting, the caller autoamtically votes yes
level . teamVoteTime [ cs_offset ] = level . time ;
level . teamVoteYes [ cs_offset ] = 1 ;
level . teamVoteNo [ cs_offset ] = 0 ;
for ( i = 0 ; i < level . maxclients ; i + + ) {
if ( level . clients [ i ] . sess . sessionTeam = = team )
level . clients [ i ] . ps . eFlags & = ~ EF_TEAMVOTED ;
}
ent - > client - > ps . eFlags | = EF_TEAMVOTED ;
trap_SetConfigstring ( CS_TEAMVOTE_TIME + cs_offset , va ( " %i " , level . teamVoteTime [ cs_offset ] ) ) ;
trap_SetConfigstring ( CS_TEAMVOTE_STRING + cs_offset , level . teamVoteString [ cs_offset ] ) ;
trap_SetConfigstring ( CS_TEAMVOTE_YES + cs_offset , va ( " %i " , level . teamVoteYes [ cs_offset ] ) ) ;
trap_SetConfigstring ( CS_TEAMVOTE_NO + cs_offset , va ( " %i " , level . teamVoteNo [ cs_offset ] ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_TeamVote_f
= = = = = = = = = = = = = = = = = =
*/
void Cmd_TeamVote_f ( gentity_t * ent ) {
int team , cs_offset ;
char msg [ 64 ] ;
team = ent - > client - > sess . sessionTeam ;
if ( team = = TEAM_RED )
cs_offset = 0 ;
else if ( team = = TEAM_BLUE )
cs_offset = 1 ;
else
return ;
if ( ! level . teamVoteTime [ cs_offset ] ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOTEAMVOTEINPROG " ) ) ) ;
return ;
}
if ( ent - > client - > ps . eFlags & EF_TEAMVOTED ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " TEAMVOTEALREADYCAST " ) ) ) ;
return ;
}
if ( ent - > client - > sess . sessionTeam = = TEAM_SPECTATOR ) {
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOVOTEASSPEC " ) ) ) ;
return ;
}
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " PLTEAMVOTECAST " ) ) ) ;
ent - > client - > ps . eFlags | = EF_TEAMVOTED ;
trap_Argv ( 1 , msg , sizeof ( msg ) ) ;
if ( msg [ 0 ] = = ' y ' | | msg [ 1 ] = = ' Y ' | | msg [ 1 ] = = ' 1 ' ) {
level . teamVoteYes [ cs_offset ] + + ;
trap_SetConfigstring ( CS_TEAMVOTE_YES + cs_offset , va ( " %i " , level . teamVoteYes [ cs_offset ] ) ) ;
} else {
level . teamVoteNo [ cs_offset ] + + ;
trap_SetConfigstring ( CS_TEAMVOTE_NO + cs_offset , va ( " %i " , level . teamVoteNo [ cs_offset ] ) ) ;
}
// a majority will be determined in TeamCheckVote, which will also account
// for players entering or leaving
}
/*
= = = = = = = = = = = = = = = = =
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 \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NOCHEATS " ) ) ) ;
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 ) ;
}
/*
= = = = = = = = = = = = = = = = =
Cmd_Stats_f
= = = = = = = = = = = = = = = = =
*/
void Cmd_Stats_f ( gentity_t * ent ) {
/*
int max , n , i ;
max = trap_AAS_PointReachabilityAreaIndex ( NULL ) ;
n = 0 ;
for ( i = 0 ; i < max ; i + + ) {
if ( ent - > client - > areabits [ i > > 3 ] & ( 1 < < ( i & 7 ) ) )
n + + ;
}
//trap_SendServerCommand( ent-g_entities, va("print \"visited %d of %d areas\n\"", n, max));
trap_SendServerCommand ( ent - g_entities , va ( " print \" %d%% level coverage \n \" " , n * 100 / max ) ) ;
*/
}
int G_ItemUsable ( playerState_t * ps , int forcedUse )
{
vec3_t fwd , fwdorg , dest , pos ;
vec3_t yawonly ;
vec3_t mins , maxs ;
vec3_t trtest ;
trace_t tr ;
if ( ps - > usingATST )
{
return 0 ;
}
if ( ps - > pm_flags & PMF_USE_ITEM_HELD )
{ //force to let go first
return 0 ;
}
if ( ! forcedUse )
{
forcedUse = bg_itemlist [ ps - > stats [ STAT_HOLDABLE_ITEM ] ] . giTag ;
}
switch ( forcedUse )
{
case HI_MEDPAC :
if ( ps - > stats [ STAT_HEALTH ] > = ps - > stats [ STAT_MAX_HEALTH ] )
{
return 0 ;
}
return 1 ;
case HI_SEEKER :
if ( ps - > eFlags & EF_SEEKERDRONE )
{
G_AddEvent ( & g_entities [ ps - > clientNum ] , EV_ITEMUSEFAIL , SEEKER_ALREADYDEPLOYED ) ;
return 0 ;
}
return 1 ;
case HI_SENTRY_GUN :
if ( ps - > fd . sentryDeployed )
{
G_AddEvent ( & g_entities [ ps - > clientNum ] , EV_ITEMUSEFAIL , SENTRY_ALREADYPLACED ) ;
return 0 ;
}
yawonly [ ROLL ] = 0 ;
yawonly [ PITCH ] = 0 ;
yawonly [ YAW ] = ps - > viewangles [ YAW ] ;
VectorSet ( mins , - 8 , - 8 , 0 ) ;
VectorSet ( maxs , 8 , 8 , 24 ) ;
AngleVectors ( yawonly , fwd , NULL , NULL ) ;
fwdorg [ 0 ] = ps - > origin [ 0 ] + fwd [ 0 ] * 64 ;
fwdorg [ 1 ] = ps - > origin [ 1 ] + fwd [ 1 ] * 64 ;
fwdorg [ 2 ] = ps - > origin [ 2 ] + fwd [ 2 ] * 64 ;
trtest [ 0 ] = fwdorg [ 0 ] + fwd [ 0 ] * 16 ;
trtest [ 1 ] = fwdorg [ 1 ] + fwd [ 1 ] * 16 ;
trtest [ 2 ] = fwdorg [ 2 ] + fwd [ 2 ] * 16 ;
trap_Trace ( & tr , ps - > origin , mins , maxs , trtest , ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( ( tr . fraction ! = 1 & & tr . entityNum ! = ps - > clientNum ) | | tr . startsolid | | tr . allsolid )
{
G_AddEvent ( & g_entities [ ps - > clientNum ] , EV_ITEMUSEFAIL , SENTRY_NOROOM ) ;
return 0 ;
}
return 1 ;
case HI_SHIELD :
mins [ 0 ] = - 8 ;
mins [ 1 ] = - 8 ;
mins [ 2 ] = 0 ;
maxs [ 0 ] = 8 ;
maxs [ 1 ] = 8 ;
maxs [ 2 ] = 8 ;
AngleVectors ( ps - > viewangles , fwd , NULL , NULL ) ;
fwd [ 2 ] = 0 ;
VectorMA ( ps - > origin , 64 , fwd , dest ) ;
trap_Trace ( & tr , ps - > origin , mins , maxs , dest , ps - > clientNum , MASK_SHOT ) ;
if ( tr . fraction > 0.9 & & ! tr . startsolid & & ! tr . allsolid )
{
VectorCopy ( tr . endpos , pos ) ;
VectorSet ( dest , pos [ 0 ] , pos [ 1 ] , pos [ 2 ] - 4096 ) ;
trap_Trace ( & tr , pos , mins , maxs , dest , ps - > clientNum , MASK_SOLID ) ;
if ( ! tr . startsolid & & ! tr . allsolid )
{
return 1 ;
}
}
G_AddEvent ( & g_entities [ ps - > clientNum ] , EV_ITEMUSEFAIL , SHIELD_NOROOM ) ;
return 0 ;
default :
return 1 ;
}
}
extern int saberOffSound ;
extern int saberOnSound ;
void Cmd_ToggleSaber_f ( gentity_t * ent )
{
if ( ! saberOffSound | | ! saberOnSound )
{
saberOffSound = G_SoundIndex ( " sound/weapons/saber/saberoffquick.wav " ) ;
saberOnSound = G_SoundIndex ( " sound/weapons/saber/saberon.wav " ) ;
}
if ( ent - > client - > ps . saberInFlight )
{
return ;
}
if ( ent - > client - > ps . forceHandExtend ! = HANDEXTEND_NONE )
{
return ;
}
if ( ent - > client - > ps . weapon ! = WP_SABER )
{
return ;
}
// if (ent->client->ps.duelInProgress && !ent->client->ps.saberHolstered)
// {
// return;
// }
if ( ent - > client - > ps . duelTime > = level . time )
{
return ;
}
if ( ent - > client & & ent - > client - > ps . weaponTime < 1 )
{
if ( ent - > client - > ps . saberHolstered )
{
ent - > client - > ps . saberHolstered = qfalse ;
G_Sound ( ent , CHAN_AUTO , saberOnSound ) ;
}
else
{
ent - > client - > ps . saberHolstered = qtrue ;
G_Sound ( ent , CHAN_AUTO , saberOffSound ) ;
//prevent anything from being done for 400ms after holster
ent - > client - > ps . weaponTime = 400 ;
}
}
}
void Cmd_SaberAttackCycle_f ( gentity_t * ent )
{
int selectLevel = 0 ;
if ( ! ent | | ! ent - > client )
{
return ;
}
/*
if ( ent - > client - > ps . weaponTime > 0 )
{ //no switching attack level when busy
return ;
}
*/
if ( ent - > client - > saberCycleQueue )
{ //resume off of the queue if we haven't gotten a chance to update it yet
selectLevel = ent - > client - > saberCycleQueue ;
}
else
{
selectLevel = ent - > client - > ps . fd . saberAnimLevel ;
}
selectLevel + + ;
if ( selectLevel > ent - > client - > ps . fd . forcePowerLevel [ FP_SABERATTACK ] )
{
selectLevel = FORCE_LEVEL_1 ;
}
switch ( selectLevel )
{
case FORCE_LEVEL_1 :
trap_SendServerCommand ( ent - g_entities , " print \" Saber Attack Set: fast \n \" " ) ;
break ;
case FORCE_LEVEL_2 :
trap_SendServerCommand ( ent - g_entities , " print \" Saber Attack Set: medium \n \" " ) ;
break ;
case FORCE_LEVEL_3 :
trap_SendServerCommand ( ent - g_entities , " print \" Saber Attack Set: strong \n \" " ) ;
break ;
}
if ( ent - > client - > ps . weaponTime < = 0 )
{ //not busy, set it now
ent - > client - > ps . fd . saberAnimLevel = selectLevel ;
}
else
{ //can't set it now or we might cause unexpected chaining, so queue it
ent - > client - > saberCycleQueue = selectLevel ;
}
}
qboolean G_OtherPlayersDueling ( void )
{
int i = 0 ;
gentity_t * ent ;
while ( i < MAX_CLIENTS )
{
ent = & g_entities [ i ] ;
if ( ent & & ent - > inuse & & ent - > client & & ent - > client - > ps . duelInProgress )
{
return qtrue ;
}
i + + ;
}
return qfalse ;
}
void Cmd_EngageDuel_f ( gentity_t * ent )
{
trace_t tr ;
vec3_t forward , fwdOrg ;
if ( ! g_privateDuel . integer )
{
return ;
}
if ( g_gametype . integer = = GT_TOURNAMENT )
{ //rather pointless in this mode..
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NODUEL_GAMETYPE " ) ) ) ;
return ;
}
if ( g_gametype . integer > = GT_TEAM )
{ //no private dueling in team modes
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " NODUEL_GAMETYPE " ) ) ) ;
return ;
}
if ( ent - > client - > ps . duelTime > = level . time )
{
return ;
}
if ( ent - > client - > ps . weapon ! = WP_SABER )
{
return ;
}
/*
if ( ! ent - > client - > ps . saberHolstered )
{ //must have saber holstered at the start of the duel
return ;
}
*/
//NOTE: No longer doing this..
if ( ent - > client - > ps . saberInFlight )
{
return ;
}
if ( ent - > client - > ps . duelInProgress )
{
return ;
}
//New: Don't let a player duel if he just did and hasn't waited 10 seconds yet (note: If someone challenges him, his duel timer will reset so he can accept)
if ( ent - > client - > ps . fd . privateDuelTime > level . time )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " CANTDUEL_JUSTDID " ) ) ) ;
return ;
}
if ( G_OtherPlayersDueling ( ) )
{
trap_SendServerCommand ( ent - g_entities , va ( " print \" %s \n \" " , G_GetStripEdString ( " SVINGAME " , " CANTDUEL_BUSY " ) ) ) ;
return ;
}
AngleVectors ( ent - > client - > ps . viewangles , forward , NULL , NULL ) ;
fwdOrg [ 0 ] = ent - > client - > ps . origin [ 0 ] + forward [ 0 ] * 256 ;
fwdOrg [ 1 ] = ent - > client - > ps . origin [ 1 ] + forward [ 1 ] * 256 ;
fwdOrg [ 2 ] = ( ent - > client - > ps . origin [ 2 ] + ent - > client - > ps . viewheight ) + forward [ 2 ] * 256 ;
trap_Trace ( & tr , ent - > client - > ps . origin , NULL , NULL , fwdOrg , ent - > s . number , MASK_PLAYERSOLID ) ;
if ( tr . fraction ! = 1 & & tr . entityNum < MAX_CLIENTS )
{
gentity_t * challenged = & g_entities [ tr . entityNum ] ;
if ( ! challenged | | ! challenged - > client | | ! challenged - > inuse | |
challenged - > health < 1 | | challenged - > client - > ps . stats [ STAT_HEALTH ] < 1 | |
challenged - > client - > ps . weapon ! = WP_SABER | | challenged - > client - > ps . duelInProgress | |
challenged - > client - > ps . saberInFlight )
{
return ;
}
if ( g_gametype . integer > = GT_TEAM & & OnSameTeam ( ent , challenged ) )
{
return ;
}
if ( challenged - > client - > ps . duelIndex = = ent - > s . number & & challenged - > client - > ps . duelTime > = level . time )
{
trap_SendServerCommand ( /*challenged-g_entities*/ - 1 , va ( " print \" %s %s %s! \n \" " , challenged - > client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " PLDUELACCEPT " ) , ent - > client - > pers . netname ) ) ;
ent - > client - > ps . duelInProgress = qtrue ;
challenged - > client - > ps . duelInProgress = qtrue ;
ent - > client - > ps . duelTime = level . time + 2000 ;
challenged - > client - > ps . duelTime = level . time + 2000 ;
G_AddEvent ( ent , EV_PRIVATE_DUEL , 1 ) ;
G_AddEvent ( challenged , EV_PRIVATE_DUEL , 1 ) ;
//Holster their sabers now, until the duel starts (then they'll get auto-turned on to look cool)
if ( ! ent - > client - > ps . saberHolstered )
{
G_Sound ( ent , CHAN_AUTO , saberOffSound ) ;
ent - > client - > ps . weaponTime = 400 ;
ent - > client - > ps . saberHolstered = qtrue ;
}
if ( ! challenged - > client - > ps . saberHolstered )
{
G_Sound ( challenged , CHAN_AUTO , saberOffSound ) ;
challenged - > client - > ps . weaponTime = 400 ;
challenged - > client - > ps . saberHolstered = qtrue ;
}
}
else
{
//Print the message that a player has been challenged in private, only announce the actual duel initiation in private
trap_SendServerCommand ( challenged - g_entities , va ( " cp \" %s %s \n \" " , ent - > client - > pers . netname , G_GetStripEdString ( " SVINGAME " , " PLDUELCHALLENGE " ) ) ) ;
trap_SendServerCommand ( ent - g_entities , va ( " cp \" %s %s \n \" " , G_GetStripEdString ( " SVINGAME " , " PLDUELCHALLENGED " ) , challenged - > client - > pers . netname ) ) ;
}
challenged - > client - > ps . fd . privateDuelTime = 0 ; //reset the timer in case this player just got out of a duel. He should still be able to accept the challenge.
ent - > client - > ps . forceHandExtend = HANDEXTEND_DUELCHALLENGE ;
ent - > client - > ps . forceHandExtendTime = level . time + 1000 ;
ent - > client - > ps . duelIndex = challenged - > s . number ;
ent - > client - > ps . duelTime = level . time + 5000 ;
}
}
/*
= = = = = = = = = = = = = = = = =
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 " ) = = 0 ) {
Cmd_Voice_f ( ent , SAY_ALL , qfalse , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " vsay_team " ) = = 0 ) {
Cmd_Voice_f ( ent , SAY_TEAM , qfalse , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " vtell " ) = = 0 ) {
Cmd_VoiceTell_f ( ent , qfalse ) ;
return ;
}
if ( Q_stricmp ( cmd , " vosay " ) = = 0 ) {
Cmd_Voice_f ( ent , SAY_ALL , qfalse , qtrue ) ;
return ;
}
if ( Q_stricmp ( cmd , " vosay_team " ) = = 0 ) {
Cmd_Voice_f ( ent , SAY_TEAM , qfalse , qtrue ) ;
return ;
}
if ( Q_stricmp ( cmd , " votell " ) = = 0 ) {
Cmd_VoiceTell_f ( ent , qtrue ) ;
return ;
}
if ( Q_stricmp ( cmd , " vtaunt " ) = = 0 ) {
Cmd_VoiceTaunt_f ( ent ) ;
return ;
}
if ( Q_stricmp ( cmd , " score " ) = = 0 ) {
Cmd_Score_f ( ent ) ;
return ;
}
// ignore all other commands when at intermission
if ( level . intermissiontime ) {
Cmd_Say_f ( ent , qfalse , qtrue ) ;
return ;
}
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 , " teamtask " ) = = 0 )
Cmd_TeamTask_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 , " team " ) = = 0 )
Cmd_Team_f ( ent ) ;
else if ( Q_stricmp ( cmd , " forcechanged " ) = = 0 )
Cmd_ForceChanged_f ( ent ) ;
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 , " callteamvote " ) = = 0 )
Cmd_CallTeamVote_f ( ent ) ;
else if ( Q_stricmp ( cmd , " teamvote " ) = = 0 )
Cmd_TeamVote_f ( ent ) ;
else if ( Q_stricmp ( cmd , " gc " ) = = 0 )
Cmd_GameCommand_f ( ent ) ;
else if ( Q_stricmp ( cmd , " setviewpos " ) = = 0 )
Cmd_SetViewpos_f ( ent ) ;
else if ( Q_stricmp ( cmd , " stats " ) = = 0 )
Cmd_Stats_f ( ent ) ;
else if ( Q_stricmp ( cmd , " sv_saberswitch " ) = = 0 )
Cmd_ToggleSaber_f ( ent ) ;
else if ( Q_stricmp ( cmd , " engage_duel " ) = = 0 )
Cmd_EngageDuel_f ( ent ) ;
else if ( Q_stricmp ( cmd , " force_heal " ) = = 0 )
ForceHeal ( ent ) ;
else if ( Q_stricmp ( cmd , " force_speed " ) = = 0 )
ForceSpeed ( ent , 0 ) ;
else if ( Q_stricmp ( cmd , " force_throw " ) = = 0 )
ForceThrow ( ent , qfalse ) ;
else if ( Q_stricmp ( cmd , " force_pull " ) = = 0 )
ForceThrow ( ent , qtrue ) ;
else if ( Q_stricmp ( cmd , " force_distract " ) = = 0 )
ForceTelepathy ( ent ) ;
else if ( Q_stricmp ( cmd , " force_rage " ) = = 0 )
ForceRage ( ent ) ;
else if ( Q_stricmp ( cmd , " force_protect " ) = = 0 )
ForceProtect ( ent ) ;
else if ( Q_stricmp ( cmd , " force_absorb " ) = = 0 )
ForceAbsorb ( ent ) ;
else if ( Q_stricmp ( cmd , " force_healother " ) = = 0 )
ForceTeamHeal ( ent ) ;
else if ( Q_stricmp ( cmd , " force_forcepowerother " ) = = 0 )
ForceTeamForceReplenish ( ent ) ;
else if ( Q_stricmp ( cmd , " force_seeing " ) = = 0 )
ForceSeeing ( ent ) ;
else if ( Q_stricmp ( cmd , " use_seeker " ) = = 0 )
{
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_SEEKER ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_SEEKER ) )
{
ItemUse_Seeker ( ent ) ;
G_AddEvent ( ent , EV_USE_ITEM0 + HI_SEEKER , 0 ) ;
ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & = ~ ( 1 < < HI_SEEKER ) ;
}
}
else if ( Q_stricmp ( cmd , " use_field " ) = = 0 )
{
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_SHIELD ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_SHIELD ) )
{
ItemUse_Shield ( ent ) ;
G_AddEvent ( ent , EV_USE_ITEM0 + HI_SHIELD , 0 ) ;
ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & = ~ ( 1 < < HI_SHIELD ) ;
}
}
else if ( Q_stricmp ( cmd , " use_bacta " ) = = 0 )
{
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_MEDPAC ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_MEDPAC ) )
{
ItemUse_MedPack ( ent ) ;
G_AddEvent ( ent , EV_USE_ITEM0 + HI_MEDPAC , 0 ) ;
ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & = ~ ( 1 < < HI_MEDPAC ) ;
}
}
else if ( Q_stricmp ( cmd , " use_electrobinoculars " ) = = 0 )
{
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_BINOCULARS ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_BINOCULARS ) )
{
ItemUse_Binoculars ( ent ) ;
if ( ent - > client - > ps . zoomMode = = 0 )
{
G_AddEvent ( ent , EV_USE_ITEM0 + HI_BINOCULARS , 1 ) ;
}
else
{
G_AddEvent ( ent , EV_USE_ITEM0 + HI_BINOCULARS , 2 ) ;
}
}
}
else if ( Q_stricmp ( cmd , " zoom " ) = = 0 )
{ //cheap way of doing this
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_BINOCULARS ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_BINOCULARS ) )
{
ItemUse_Binoculars ( ent ) ;
if ( ent - > client - > ps . zoomMode = = 0 )
{
G_AddEvent ( ent , EV_USE_ITEM0 + HI_BINOCULARS , 1 ) ;
}
else
{
G_AddEvent ( ent , EV_USE_ITEM0 + HI_BINOCULARS , 2 ) ;
}
}
}
else if ( Q_stricmp ( cmd , " use_sentry " ) = = 0 )
{
if ( ( ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & ( 1 < < HI_SENTRY_GUN ) ) & &
G_ItemUsable ( & ent - > client - > ps , HI_SENTRY_GUN ) )
{
ItemUse_Sentry ( ent ) ;
G_AddEvent ( ent , EV_USE_ITEM0 + HI_SENTRY_GUN , 0 ) ;
ent - > client - > ps . stats [ STAT_HOLDABLE_ITEMS ] & = ~ ( 1 < < HI_SENTRY_GUN ) ;
}
}
else if ( Q_stricmp ( cmd , " bot_order " ) = = 0 )
{
BotOrder ( ent , atoi ( ConcatArgs ( 1 ) ) , atoi ( ConcatArgs ( 2 ) ) ) ;
}
else if ( Q_stricmp ( cmd , " saberAttackCycle " ) = = 0 )
{
Cmd_SaberAttackCycle_f ( ent ) ;
}
else if ( Q_stricmp ( cmd , " #mm " ) = = 0 & & CheatsOk ( ent ) )
{
G_PlayerBecomeATST ( ent ) ;
}
else if ( Q_stricmp ( cmd , " thedestroyer " ) = = 0 & & CheatsOk ( ent ) & & ent & & ent - > client & & ent - > client - > ps . saberHolstered & & ent - > client - > ps . weapon = = WP_SABER )
{
Cmd_ToggleSaber_f ( ent ) ;
if ( ! ent - > client - > ps . saberHolstered )
{
if ( ent - > client - > ps . dualBlade )
{
ent - > client - > ps . dualBlade = qfalse ;
//ent->client->ps.fd.saberAnimLevel = FORCE_LEVEL_1;
}
else
{
ent - > client - > ps . dualBlade = qtrue ;
trap_SendServerCommand ( - 1 , va ( " print \" %sTHE DESTROYER COMETH \n \" " , S_COLOR_RED ) ) ;
G_ScreenShake ( vec3_origin , NULL , 10.0f , 800 , qtrue ) ;
//ent->client->ps.fd.saberAnimLevel = FORCE_LEVEL_3;
}
}
}
# ifdef _DEBUG
else if ( Q_stricmp ( cmd , " gotocoord " ) = = 0 & & CheatsOk ( ent ) )
{
char x [ 64 ] , y [ 64 ] , z [ 64 ] ;
vec3_t xyz ;
if ( trap_Argc ( ) < 3 )
{
return ;
}
trap_Argv ( 1 , x , sizeof ( x ) ) ;
trap_Argv ( 2 , y , sizeof ( y ) ) ;
trap_Argv ( 3 , z , sizeof ( z ) ) ;
xyz [ 0 ] = atof ( x ) ;
xyz [ 1 ] = atof ( y ) ;
xyz [ 2 ] = atof ( z ) ;
VectorCopy ( xyz , ent - > client - > ps . origin ) ;
}
# endif
/*
else if ( Q_stricmp ( cmd , " offwithmyhead " ) = = 0 )
{
DismembermentTest ( ent ) ;
}
*/
else
trap_SendServerCommand ( clientNum , va ( " print \" unknown cmd %s \n \" " , cmd ) ) ;
}