summaryrefslogtreecommitdiff
path: root/src/game/g_cmds.c
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2004-03-01 06:00:41 +0000
committerTim Angus <tim@ngus.net>2004-03-01 06:00:41 +0000
commitc3cf4a2cf6b203359501e7f964512ba7e425e4b3 (patch)
treeca1b8cfe4a4de81575cef807be354ab4a3d685f9 /src/game/g_cmds.c
parent8de2853c89a624574402d82e541e2061cc121b4a (diff)
* Reimplemented the chasecam
Diffstat (limited to 'src/game/g_cmds.c')
-rw-r--r--src/game/g_cmds.c255
1 files changed, 233 insertions, 22 deletions
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index d9d9922c..1145bad1 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -18,6 +18,90 @@
/*
==================
+G_SanitiseName
+
+Remove case and control characters from a player name
+==================
+*/
+void G_SanitiseName( 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_ClientNumberFromString
+
+Returns a player number for either a number or name string
+Returns -1 if invalid
+==================
+*/
+int G_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
+ G_SanitiseName( s, s2 );
+
+ for( idnum = 0, cl = level.clients; idnum < level.maxclients; idnum++, cl++ )
+ {
+ if( cl->pers.connected != CON_CONNECTED )
+ continue;
+
+ G_SanitiseName( 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;
+}
+
+/*
+==================
ScoreboardMessage
==================
@@ -336,17 +420,36 @@ void Cmd_Kill_f( gentity_t *ent )
/*
=================
-Cmd_Team_f
+G_ChangeTeam
=================
*/
-void Cmd_Team_f( gentity_t *ent )
+void G_ChangeTeam( gentity_t *ent, pTeam_t newTeam )
{
- int oldTeam;
- char s[MAX_TOKEN_CHARS];
+ pTeam_t oldTeam = ent->client->pers.teamSelection;
- //TA: rip out the q3a team system :)
+ ent->client->pers.teamSelection = newTeam;
- oldTeam = ent->client->pers.teamSelection;
+ if( oldTeam != newTeam )
+ {
+ level.bankCredits[ ent->client->ps.clientNum ] = 0;
+ ent->client->ps.persistant[ PERS_CREDIT ] = 0;
+ ent->client->pers.classSelection = PCL_NONE;
+ ClientSpawn( ent, NULL, NULL, NULL );
+ }
+
+ //update ClientInfo
+ ClientUserinfoChanged( ent->client->ps.clientNum );
+}
+
+/*
+=================
+Cmd_Team_f
+=================
+*/
+void Cmd_Team_f( gentity_t *ent )
+{
+ pTeam_t team;
+ char s[ MAX_TOKEN_CHARS ];
trap_Argv( 1, s, sizeof( s ) );
@@ -357,7 +460,7 @@ void Cmd_Team_f( gentity_t *ent )
}
if( !Q_stricmp( s, "spectate" ) )
- ent->client->pers.teamSelection = PTE_NONE;
+ team = PTE_NONE;
else if( !Q_stricmp( s, "aliens" ) )
{
if( g_teamForceBalance.integer && level.numAlienClients > level.numHumanClients )
@@ -367,7 +470,7 @@ void Cmd_Team_f( gentity_t *ent )
return;
}
- ent->client->pers.teamSelection = PTE_ALIENS;
+ team = PTE_ALIENS;
}
else if( !Q_stricmp( s, "humans" ) )
{
@@ -378,28 +481,19 @@ void Cmd_Team_f( gentity_t *ent )
return;
}
- ent->client->pers.teamSelection = PTE_HUMANS;
+ team = PTE_HUMANS;
}
else if( !Q_stricmp( s, "auto" ) )
{
if( level.numHumanClients > level.numAlienClients )
- ent->client->pers.teamSelection = PTE_ALIENS;
+ team = PTE_ALIENS;
else if( level.numHumanClients < level.numAlienClients )
- ent->client->pers.teamSelection = PTE_HUMANS;
+ team = PTE_HUMANS;
else
- ent->client->pers.teamSelection = PTE_ALIENS + ( rand( ) % 2 );
+ team = PTE_ALIENS + ( rand( ) % 2 );
}
- if( oldTeam != ent->client->pers.teamSelection )
- {
- level.bankCredits[ ent->client->ps.clientNum ] = 0;
- ent->client->ps.persistant[ PERS_CREDIT ] = 0;
- ent->client->pers.classSelection = PCL_NONE;
- ClientSpawn( ent, NULL, NULL, NULL );
- }
-
- //update ClientInfo
- ClientUserinfoChanged( ent->client->ps.clientNum );
+ G_ChangeTeam( ent, team );
//FIXME: put some team change broadcast code here.
}
@@ -1715,6 +1809,117 @@ void Cmd_Reload_f( gentity_t *ent )
/*
=================
+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 )
+{
+ 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;
+}
+
+/*
+=================
+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 = G_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;
+
+ // first set them to spectator
+ if( ent->client->sess.sessionTeam != TEAM_SPECTATOR )
+ G_ChangeTeam( ent, PTE_NONE );
+
+ 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;
+
+ // first set them to spectator
+ if( ent->client->sess.spectatorState == SPECTATOR_NOT )
+ G_ChangeTeam( ent, PTE_NONE );
+
+ 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't follow self
+ if( &level.clients[ clientnum ] == ent->client )
+ continue;
+
+ // 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
+}
+
+
+/*
+=================
Cmd_Test_f
=================
*/
@@ -1826,6 +2031,12 @@ void ClientCommand( int clientNum )
Cmd_Vote_f( ent );
else if( Q_stricmp( cmd, "callteamvote" ) == 0 )
Cmd_CallTeamVote_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, "teamvote" ) == 0 )
Cmd_TeamVote_f( ent );
else if( Q_stricmp( cmd, "setviewpos" ) == 0 )