Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

g_client.c File Reference

#include "g_local.h"

Include dependency graph for g_client.c:

Include dependency graph

Go to the source code of this file.

Defines

#define MAX_SPAWN_POINTS   128
#define MAX_SPAWN_POINTS   128

Functions

void BodySink (gentity_t *ent)
void ClientBegin (int clientNum)
void ClientCleanName (const char *in, char *out, int outSize)
char * ClientConnect (int clientNum, qboolean firstTime, qboolean isBot)
void ClientDisconnect (int clientNum)
void ClientSpawn (gentity_t *ent)
void ClientUserinfoChanged (int clientNum)
void CopyToBodyQue (gentity_t *ent)
void InitBodyQue (void)
team_t PickTeam (int ignoreClientNum)
void respawn (gentity_t *ent)
gentity_tSelectInitialSpawnPoint (vec3_t origin, vec3_t angles)
gentity_tSelectNearestDeathmatchSpawnPoint (vec3_t from)
gentity_tSelectRandomDeathmatchSpawnPoint (void)
gentity_tSelectRandomFurthestSpawnPoint (vec3_t avoidPoint, vec3_t origin, vec3_t angles)
gentity_tSelectSpawnPoint (vec3_t avoidPoint, vec3_t origin, vec3_t angles)
gentity_tSelectSpectatorSpawnPoint (vec3_t origin, vec3_t angles)
void SetClientViewAngle (gentity_t *ent, vec3_t angle)
void SP_info_player_deathmatch (gentity_t *ent)
void SP_info_player_intermission (gentity_t *ent)
void SP_info_player_start (gentity_t *ent)
qboolean SpotWouldTelefrag (gentity_t *spot)
team_t TeamCount (int ignoreClientNum, int team)
int TeamLeader (int team)

Variables

vec3_t playerMaxs = {15, 15, 32}
vec3_t playerMins = {-15, -15, -24}


Define Documentation

#define MAX_SPAWN_POINTS   128
 

Definition at line 142 of file g_client.c.

#define MAX_SPAWN_POINTS   128
 

Definition at line 142 of file g_client.c.


Function Documentation

void BodySink gentity_t ent  ) 
 

Definition at line 350 of file g_client.c.

References gentity_t, level, gentity_s::nextthink, gentity_s::physicsObject, entityState_s::pos, gentity_s::s, level_locals_t::time, gentity_s::timestamp, trap_UnlinkEntity(), and trajectory_t::trBase.

00350                                 {
00351     if ( level.time - ent->timestamp > 6500 ) {
00352         // the body ques are never actually freed, they are just unlinked
00353         trap_UnlinkEntity( ent );
00354         ent->physicsObject = qfalse;
00355         return; 
00356     }
00357     ent->nextthink = level.time + 100;
00358     ent->s.pos.trBase[2] -= 1;
00359 }

Here is the call graph for this function:

void ClientBegin int  clientNum  ) 
 

Definition at line 993 of file g_client.c.

References CalculateRanks(), gentity_s::client, entityState_s::clientNum, level_locals_t::clients, ClientSpawn(), clientPersistant_t::connected, playerState_s::eFlags, clientPersistant_t::enterTime, EV_PLAYER_TELEPORT_IN, g_entities, g_gametype, G_InitGentity(), G_LogPrintf(), G_TempEntity(), gclient_t, gentity_t, level, entityShared_t::linked, memset(), clientPersistant_t::netname, playerState_s::origin, gentity_s::pain, gclient_s::pers, gclient_s::ps, gentity_s::r, gentity_s::s, S_COLOR_WHITE, gclient_s::sess, clientSession_t::sessionTeam, playerTeamState_t::state, clientPersistant_t::teamState, level_locals_t::time, gentity_s::touch, trap_SendServerCommand(), trap_UnlinkEntity(), and va().

Referenced by AddBotToSpawnQueue(), G_AddBot(), G_CheckBotSpawn(), SetTeam(), SpectatorClientEndFrame(), and vmMain().

00993                                   {
00994     gentity_t   *ent;
00995     gclient_t   *client;
00996     gentity_t   *tent;
00997     int         flags;
00998 
00999     ent = g_entities + clientNum;
01000 
01001     client = level.clients + clientNum;
01002 
01003     if ( ent->r.linked ) {
01004         trap_UnlinkEntity( ent );
01005     }
01006     G_InitGentity( ent );
01007     ent->touch = 0;
01008     ent->pain = 0;
01009     ent->client = client;
01010 
01011     client->pers.connected = CON_CONNECTED;
01012     client->pers.enterTime = level.time;
01013     client->pers.teamState.state = TEAM_BEGIN;
01014 
01015     // save eflags around this, because changing teams will
01016     // cause this to happen with a valid entity, and we
01017     // want to make sure the teleport bit is set right
01018     // so the viewpoint doesn't interpolate through the
01019     // world to the new position
01020     flags = client->ps.eFlags;
01021     memset( &client->ps, 0, sizeof( client->ps ) );
01022     client->ps.eFlags = flags;
01023 
01024     // locate ent at a spawn point
01025     ClientSpawn( ent );
01026 
01027     if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
01028         // send event
01029         tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
01030         tent->s.clientNum = ent->s.clientNum;
01031 
01032         if ( g_gametype.integer != GT_TOURNAMENT  ) {
01033             trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " entered the game\n\"", client->pers.netname) );
01034         }
01035     }
01036     G_LogPrintf( "ClientBegin: %i\n", clientNum );
01037 
01038     // count current clients and rank for scoreboard
01039     CalculateRanks();
01040 }

Here is the call graph for this function:

void ClientCleanName const char *  in,
char *  out,
int  outSize
[static]
 

Definition at line 610 of file g_client.c.

References ch, ColorIndex, in, p, and Q_strncpyz().

Referenced by ClientUserinfoChanged().

00610                                                                       {
00611     int     len, colorlessLen;
00612     char    ch;
00613     char    *p;
00614     int     spaces;
00615 
00616     //save room for trailing null byte
00617     outSize--;
00618 
00619     len = 0;
00620     colorlessLen = 0;
00621     p = out;
00622     *p = 0;
00623     spaces = 0;
00624 
00625     while( 1 ) {
00626         ch = *in++;
00627         if( !ch ) {
00628             break;
00629         }
00630 
00631         // don't allow leading spaces
00632         if( !*p && ch == ' ' ) {
00633             continue;
00634         }
00635 
00636         // check colors
00637         if( ch == Q_COLOR_ESCAPE ) {
00638             // solo trailing carat is not a color prefix
00639             if( !*in ) {
00640                 break;
00641             }
00642 
00643             // don't allow black in a name, period
00644             if( ColorIndex(*in) == 0 ) {
00645                 in++;
00646                 continue;
00647             }
00648 
00649             // make sure room in dest for both chars
00650             if( len > outSize - 2 ) {
00651                 break;
00652             }
00653 
00654             *out++ = ch;
00655             *out++ = *in++;
00656             len += 2;
00657             continue;
00658         }
00659 
00660         // don't allow too many consecutive spaces
00661         if( ch == ' ' ) {
00662             spaces++;
00663             if( spaces > 3 ) {
00664                 continue;
00665             }
00666         }
00667         else {
00668             spaces = 0;
00669         }
00670 
00671         if( len > outSize - 1 ) {
00672             break;
00673         }
00674 
00675         *out++ = ch;
00676         colorlessLen++;
00677         len++;
00678     }
00679     *out = 0;
00680 
00681     // don't allow empty names
00682     if( *p == 0 || colorlessLen == 0 ) {
00683         Q_strncpyz( p, "UnnamedPlayer", outSize );
00684     }
00685 }

Here is the call graph for this function:

char* ClientConnect int  clientNum,
qboolean  firstTime,
qboolean  isBot
 

Definition at line 903 of file g_client.c.

References BroadcastTeamChange(), CalculateRanks(), gentity_s::client, level_locals_t::clients, ClientUserinfoChanged(), clientPersistant_t::connected, G_BotConnect(), g_entities, G_FilterPacket(), g_gametype, G_InitSessionData(), G_LogPrintf(), g_password, G_ReadSessionData(), gclient_t, gentity_t, GT_TEAM, Info_ValueForKey(), gentity_s::inuse, level, memset(), level_locals_t::newSession, gclient_s::pers, Q_stricmp(), gentity_s::r, S_COLOR_WHITE, strcmp(), vmCvar_t::string, entityShared_t::svFlags, trap_GetUserinfo(), trap_SendServerCommand(), va(), and value.

Referenced by G_AddBot(), and vmMain().

00903                                                                          {
00904     char        *value;
00905 //  char        *areabits;
00906     gclient_t   *client;
00907     char        userinfo[MAX_INFO_STRING];
00908     gentity_t   *ent;
00909 
00910     ent = &g_entities[ clientNum ];
00911 
00912     trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );
00913 
00914     // IP filtering
00915     // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500
00916     // recommanding PB based IP / GUID banning, the builtin system is pretty limited
00917     // check to see if they are on the banned IP list
00918     value = Info_ValueForKey (userinfo, "ip");
00919     if ( G_FilterPacket( value ) ) {
00920         return "You are banned from this server.";
00921     }
00922 
00923   // we don't check password for bots and local client
00924   // NOTE: local client <-> "ip" "localhost"
00925   //   this means this client is not running in our current process
00926     if ( !( ent->r.svFlags & SVF_BOT ) && (strcmp(value, "localhost") != 0)) {
00927         // check for a password
00928         value = Info_ValueForKey (userinfo, "password");
00929         if ( g_password.string[0] && Q_stricmp( g_password.string, "none" ) &&
00930             strcmp( g_password.string, value) != 0) {
00931             return "Invalid password";
00932         }
00933     }
00934 
00935     // they can connect
00936     ent->client = level.clients + clientNum;
00937     client = ent->client;
00938 
00939 //  areabits = client->areabits;
00940 
00941     memset( client, 0, sizeof(*client) );
00942 
00943     client->pers.connected = CON_CONNECTING;
00944 
00945     // read or initialize the session data
00946     if ( firstTime || level.newSession ) {
00947         G_InitSessionData( client, userinfo );
00948     }
00949     G_ReadSessionData( client );
00950 
00951     if( isBot ) {
00952         ent->r.svFlags |= SVF_BOT;
00953         ent->inuse = qtrue;
00954         if( !G_BotConnect( clientNum, !firstTime ) ) {
00955             return "BotConnectfailed";
00956         }
00957     }
00958 
00959     // get and distribute relevent paramters
00960     G_LogPrintf( "ClientConnect: %i\n", clientNum );
00961     ClientUserinfoChanged( clientNum );
00962 
00963     // don't do the "xxx connected" messages if they were caried over from previous level
00964     if ( firstTime ) {
00965         trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname) );
00966     }
00967 
00968     if ( g_gametype.integer >= GT_TEAM &&
00969         client->sess.sessionTeam != TEAM_SPECTATOR ) {
00970         BroadcastTeamChange( client, -1 );
00971     }
00972 
00973     // count current clients and rank for scoreboard
00974     CalculateRanks();
00975 
00976     // for statistics
00977 //  client->areabits = areabits;
00978 //  if ( !client->areabits )
00979 //      client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );
00980 
00981     return NULL;
00982 }

Here is the call graph for this function:

void ClientDisconnect int  clientNum  ) 
 

Definition at line 1276 of file g_client.c.

References BotAIShutdownClient(), CalculateRanks(), gentity_s::classname, gentity_s::client, entityState_s::clientNum, level_locals_t::clients, ClientUserinfoChanged(), CON_CONNECTED, clientPersistant_t::connected, CS_PLAYERS, EV_PLAYER_TELEPORT_OUT, g_entities, g_gametype, G_LogPrintf(), G_RemoveQueuedBotBegin(), G_TempEntity(), gentity_t, i, level_locals_t::intermissiontime, gentity_s::inuse, level, level_locals_t::maxclients, entityState_s::modelindex, playerState_s::origin, gclient_s::pers, playerState_s::persistant, gclient_s::ps, qfalse, gentity_s::r, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, level_locals_t::sortedClients, SPECTATOR_FOLLOW, clientSession_t::spectatorClient, clientSession_t::spectatorState, StopFollowing(), entityShared_t::svFlags, TEAM_SPECTATOR, TossClientCubes(), TossClientItems(), trap_SetConfigstring(), trap_UnlinkEntity(), level_locals_t::warmupTime, and clientSession_t::wins.

Referenced by vmMain().

01276                                        {
01277     gentity_t   *ent;
01278     gentity_t   *tent;
01279     int         i;
01280 
01281     // cleanup if we are kicking a bot that
01282     // hasn't spawned yet
01283     G_RemoveQueuedBotBegin( clientNum );
01284 
01285     ent = g_entities + clientNum;
01286     if ( !ent->client ) {
01287         return;
01288     }
01289 
01290     // stop any following clients
01291     for ( i = 0 ; i < level.maxclients ; i++ ) {
01292         if ( level.clients[i].sess.sessionTeam == TEAM_SPECTATOR
01293             && level.clients[i].sess.spectatorState == SPECTATOR_FOLLOW
01294             && level.clients[i].sess.spectatorClient == clientNum ) {
01295             StopFollowing( &g_entities[i] );
01296         }
01297     }
01298 
01299     // send effect if they were completely connected
01300     if ( ent->client->pers.connected == CON_CONNECTED 
01301         && ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
01302         tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
01303         tent->s.clientNum = ent->s.clientNum;
01304 
01305         // They don't get to take powerups with them!
01306         // Especially important for stuff like CTF flags
01307         TossClientItems( ent );
01308 #ifdef MISSIONPACK
01309         TossClientPersistantPowerups( ent );
01310         if( g_gametype.integer == GT_HARVESTER ) {
01311             TossClientCubes( ent );
01312         }
01313 #endif
01314 
01315     }
01316 
01317     G_LogPrintf( "ClientDisconnect: %i\n", clientNum );
01318 
01319     // if we are playing in tourney mode and losing, give a win to the other player
01320     if ( (g_gametype.integer == GT_TOURNAMENT )
01321         && !level.intermissiontime
01322         && !level.warmupTime && level.sortedClients[1] == clientNum ) {
01323         level.clients[ level.sortedClients[0] ].sess.wins++;
01324         ClientUserinfoChanged( level.sortedClients[0] );
01325     }
01326 
01327     trap_UnlinkEntity (ent);
01328     ent->s.modelindex = 0;
01329     ent->inuse = qfalse;
01330     ent->classname = "disconnected";
01331     ent->client->pers.connected = CON_DISCONNECTED;
01332     ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE;
01333     ent->client->sess.sessionTeam = TEAM_FREE;
01334 
01335     trap_SetConfigstring( CS_PLAYERS + clientNum, "");
01336 
01337     CalculateRanks();
01338 
01339     if ( ent->r.svFlags & SVF_BOT ) {
01340         BotAIShutdownClient( clientNum, qfalse );
01341     }
01342 }

Here is the call graph for this function:

void ClientSpawn gentity_t ent  ) 
 

Definition at line 1051 of file g_client.c.

References gclient_s::accuracy_hits, gclient_s::accuracy_shots, atoi, BG_PlayerStateToEntityState(), gentity_s::classname, gentity_s::client, ClientEndFrame(), level_locals_t::clients, ClientThink(), gentity_s::clipmask, clientPersistant_t::cmd, entityShared_t::contents, entityShared_t::currentOrigin, gentity_s::die, EF_TELEPORT_BIT, EF_VOTED, entityState_s::eFlags, playerState_s::eFlags, playerState_s::eventSequence, gentity_s::flags, g_entities, g_gametype, g_inactivity, G_KillBox(), G_SetOrigin(), G_UseTargets(), gclient_t, gentity_t, entityState_s::groundEntityNum, gentity_s::health, i, Info_ValueForKey(), clientPersistant_t::initialSpawn, vmCvar_t::integer, level_locals_t::intermissiontime, gentity_s::inuse, level, clientPersistant_t::localClient, entityShared_t::maxs, memset(), entityShared_t::mins, MoveClientToIntermission(), playerState_s::origin, gclient_s::pers, playerState_s::persistant, playerState_s::ping, playerMaxs, playerMins, gclient_s::ps, qtrue, gentity_s::r, gentity_s::s, SelectCTFSpawnPoint(), SelectInitialSpawnPoint(), SelectSpawnPoint(), SelectSpectatorSpawnPoint(), usercmd_s::serverTime, gclient_s::sess, clientSession_t::sessionTeam, SetClientViewAngle(), playerTeamState_t::state, entityShared_t::svFlags, gentity_s::takedamage, clientPersistant_t::teamState, level_locals_t::time, trap_GetUsercmd(), trap_GetUserinfo(), trap_LinkEntity(), vec3_t, VectorCopy, gentity_s::waterlevel, gentity_s::watertype, and WP_NUM_WEAPONS.

Referenced by ClientBegin(), G_RankRunFrame(), and respawn().

01051                                  {
01052     int     index;
01053     vec3_t  spawn_origin, spawn_angles;
01054     gclient_t   *client;
01055     int     i;
01056     clientPersistant_t  saved;
01057     clientSession_t     savedSess;
01058     int     persistant[MAX_PERSISTANT];
01059     gentity_t   *spawnPoint;
01060     int     flags;
01061     int     savedPing;
01062 //  char    *savedAreaBits;
01063     int     accuracy_hits, accuracy_shots;
01064     int     eventSequence;
01065     char    userinfo[MAX_INFO_STRING];
01066 
01067     index = ent - g_entities;
01068     client = ent->client;
01069 
01070     // find a spawn point
01071     // do it before setting health back up, so farthest
01072     // ranging doesn't count this client
01073     if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
01074         spawnPoint = SelectSpectatorSpawnPoint ( 
01075                         spawn_origin, spawn_angles);
01076     } else if (g_gametype.integer >= GT_CTF ) {
01077         // all base oriented team games use the CTF spawn points
01078         spawnPoint = SelectCTFSpawnPoint ( 
01079                         client->sess.sessionTeam, 
01080                         client->pers.teamState.state, 
01081                         spawn_origin, spawn_angles);
01082     } else {
01083         do {
01084             // the first spawn should be at a good looking spot
01085             if ( !client->pers.initialSpawn && client->pers.localClient ) {
01086                 client->pers.initialSpawn = qtrue;
01087                 spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
01088             } else {
01089                 // don't spawn near existing origin if possible
01090                 spawnPoint = SelectSpawnPoint ( 
01091                     client->ps.origin, 
01092                     spawn_origin, spawn_angles);
01093             }
01094 
01095             // Tim needs to prevent bots from spawning at the initial point
01096             // on q3dm0...
01097             if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
01098                 continue;   // try again
01099             }
01100             // just to be symetric, we have a nohumans option...
01101             if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
01102                 continue;   // try again
01103             }
01104 
01105             break;
01106 
01107         } while ( 1 );
01108     }
01109     client->pers.teamState.state = TEAM_ACTIVE;
01110 
01111     // always clear the kamikaze flag
01112     ent->s.eFlags &= ~EF_KAMIKAZE;
01113 
01114     // toggle the teleport bit so the client knows to not lerp
01115     // and never clear the voted flag
01116     flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
01117     flags ^= EF_TELEPORT_BIT;
01118 
01119     // clear everything but the persistant data
01120 
01121     saved = client->pers;
01122     savedSess = client->sess;
01123     savedPing = client->ps.ping;
01124 //  savedAreaBits = client->areabits;
01125     accuracy_hits = client->accuracy_hits;
01126     accuracy_shots = client->accuracy_shots;
01127     for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
01128         persistant[i] = client->ps.persistant[i];
01129     }
01130     eventSequence = client->ps.eventSequence;
01131 
01132     memset (client, 0, sizeof(*client)); // bk FIXME: Com_Memset?
01133 
01134     client->pers = saved;
01135     client->sess = savedSess;
01136     client->ps.ping = savedPing;
01137 //  client->areabits = savedAreaBits;
01138     client->accuracy_hits = accuracy_hits;
01139     client->accuracy_shots = accuracy_shots;
01140     client->lastkilled_client = -1;
01141 
01142     for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
01143         client->ps.persistant[i] = persistant[i];
01144     }
01145     client->ps.eventSequence = eventSequence;
01146     // increment the spawncount so the client will detect the respawn
01147     client->ps.persistant[PERS_SPAWN_COUNT]++;
01148     client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;
01149 
01150     client->airOutTime = level.time + 12000;
01151 
01152     trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
01153     // set max health
01154     client->pers.maxHealth = atoi( Info_ValueForKey( userinfo, "handicap" ) );
01155     if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
01156         client->pers.maxHealth = 100;
01157     }
01158     // clear entity values
01159     client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
01160     client->ps.eFlags = flags;
01161 
01162     ent->s.groundEntityNum = ENTITYNUM_NONE;
01163     ent->client = &level.clients[index];
01164     ent->takedamage = qtrue;
01165     ent->inuse = qtrue;
01166     ent->classname = "player";
01167     ent->r.contents = CONTENTS_BODY;
01168     ent->clipmask = MASK_PLAYERSOLID;
01169     ent->die = player_die;
01170     ent->waterlevel = 0;
01171     ent->watertype = 0;
01172     ent->flags = 0;
01173     
01174     VectorCopy (playerMins, ent->r.mins);
01175     VectorCopy (playerMaxs, ent->r.maxs);
01176 
01177     client->ps.clientNum = index;
01178 
01179     client->ps.stats[STAT_WEAPONS] = ( 1 << WP_MACHINEGUN );
01180     if ( g_gametype.integer == GT_TEAM ) {
01181         client->ps.ammo[WP_MACHINEGUN] = 50;
01182     } else {
01183         client->ps.ammo[WP_MACHINEGUN] = 100;
01184     }
01185 
01186     client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_GAUNTLET );
01187     client->ps.ammo[WP_GAUNTLET] = -1;
01188     client->ps.ammo[WP_GRAPPLING_HOOK] = -1;
01189 
01190     // health will count down towards max_health
01191     ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;
01192 
01193     G_SetOrigin( ent, spawn_origin );
01194     VectorCopy( spawn_origin, client->ps.origin );
01195 
01196     // the respawned flag will be cleared after the attack and jump keys come up
01197     client->ps.pm_flags |= PMF_RESPAWNED;
01198 
01199     trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
01200     SetClientViewAngle( ent, spawn_angles );
01201 
01202     if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
01203 
01204     } else {
01205         G_KillBox( ent );
01206         trap_LinkEntity (ent);
01207 
01208         // force the base weapon up
01209         client->ps.weapon = WP_MACHINEGUN;
01210         client->ps.weaponstate = WEAPON_READY;
01211 
01212     }
01213 
01214     // don't allow full run speed for a bit
01215     client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
01216     client->ps.pm_time = 100;
01217 
01218     client->respawnTime = level.time;
01219     client->inactivityTime = level.time + g_inactivity.integer * 1000;
01220     client->latched_buttons = 0;
01221 
01222     // set default animations
01223     client->ps.torsoAnim = TORSO_STAND;
01224     client->ps.legsAnim = LEGS_IDLE;
01225 
01226     if ( level.intermissiontime ) {
01227         MoveClientToIntermission( ent );
01228     } else {
01229         // fire the targets of the spawn point
01230         G_UseTargets( spawnPoint, ent );
01231 
01232         // select the highest weapon number available, after any
01233         // spawn given items have fired
01234         client->ps.weapon = 1;
01235         for ( i = WP_NUM_WEAPONS - 1 ; i > 0 ; i-- ) {
01236             if ( client->ps.stats[STAT_WEAPONS] & ( 1 << i ) ) {
01237                 client->ps.weapon = i;
01238                 break;
01239             }
01240         }
01241     }
01242 
01243     // run a client frame to drop exactly to the floor,
01244     // initialize animations and other things
01245     client->ps.commandTime = level.time - 100;
01246     ent->client->pers.cmd.serverTime = level.time;
01247     ClientThink( ent-g_entities );
01248 
01249     // positively link the client, even if the command times are weird
01250     if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
01251         BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
01252         VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
01253         trap_LinkEntity( ent );
01254     }
01255 
01256     // run the presend to set anything else
01257     ClientEndFrame( ent );
01258 
01259     // clear entity state values
01260     BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
01261 }

Here is the call graph for this function:

void ClientUserinfoChanged int  clientNum  ) 
 

Definition at line 699 of file g_client.c.

References atoi, gentity_s::client, ClientCleanName(), clientPersistant_t::connected, CS_PLAYERS, g_entities, g_gametype, G_LogPrintf(), gclient_t, gentity_t, GT_TEAM, Info_Validate(), Info_ValueForKey(), clientPersistant_t::localClient, clientSession_t::losses, clientPersistant_t::maxHealth, clientPersistant_t::netname, gclient_s::pers, PickTeam(), playerState_s::powerups, clientPersistant_t::predictItemPickup, gclient_s::ps, Q_stricmp(), Q_strncpyz(), gentity_s::r, s, S_COLOR_WHITE, gclient_s::sess, clientSession_t::sessionTeam, clientSession_t::spectatorState, playerState_s::stats, strcmp(), strcpy(), entityShared_t::svFlags, clientPersistant_t::teamInfo, clientSession_t::teamLeader, trap_GetUserinfo(), trap_SendServerCommand(), trap_SetConfigstring(), va(), and clientSession_t::wins.

Referenced by AdjustTournamentScores(), BotSetUserInfo(), ClientConnect(), ClientDisconnect(), Cmd_TeamTask_f(), SetLeader(), SetTeam(), and vmMain().

00699                                             {
00700     gentity_t *ent;
00701     int     teamTask, teamLeader, team, health;
00702     char    *s;
00703     char    model[MAX_QPATH];
00704     char    headModel[MAX_QPATH];
00705     char    oldname[MAX_STRING_CHARS];
00706     gclient_t   *client;
00707     char    c1[MAX_INFO_STRING];
00708     char    c2[MAX_INFO_STRING];
00709     char    redTeam[MAX_INFO_STRING];
00710     char    blueTeam[MAX_INFO_STRING];
00711     char    userinfo[MAX_INFO_STRING];
00712 
00713     ent = g_entities + clientNum;
00714     client = ent->client;
00715 
00716     trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );
00717 
00718     // check for malformed or illegal info strings
00719     if ( !Info_Validate(userinfo) ) {
00720         strcpy (userinfo, "\\name\\badinfo");
00721     }
00722 
00723     // check for local client
00724     s = Info_ValueForKey( userinfo, "ip" );
00725     if ( !strcmp( s, "localhost" ) ) {
00726         client->pers.localClient = qtrue;
00727     }
00728 
00729     // check the item prediction
00730     s = Info_ValueForKey( userinfo, "cg_predictItems" );
00731     if ( !atoi( s ) ) {
00732         client->pers.predictItemPickup = qfalse;
00733     } else {
00734         client->pers.predictItemPickup = qtrue;
00735     }
00736 
00737     // set name
00738     Q_strncpyz ( oldname, client->pers.netname, sizeof( oldname ) );
00739     s = Info_ValueForKey (userinfo, "name");
00740     ClientCleanName( s, client->pers.netname, sizeof(client->pers.netname) );
00741 
00742     if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
00743         if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
00744             Q_strncpyz( client->pers.netname, "scoreboard", sizeof(client->pers.netname) );
00745         }
00746     }
00747 
00748     if ( client->pers.connected == CON_CONNECTED ) {
00749         if ( strcmp( oldname, client->pers.netname ) ) {
00750             trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, 
00751                 client->pers.netname) );
00752         }
00753     }
00754 
00755     // set max health
00756 #ifdef MISSIONPACK
00757     if (client->ps.powerups[PW_GUARD]) {
00758         client->pers.maxHealth = 200;
00759     } else {
00760         health = atoi( Info_ValueForKey( userinfo, "handicap" ) );
00761         client->pers.maxHealth = health;
00762         if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
00763             client->pers.maxHealth = 100;
00764         }
00765     }
00766 #else
00767     health = atoi( Info_ValueForKey( userinfo, "handicap" ) );
00768     client->pers.maxHealth = health;
00769     if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
00770         client->pers.maxHealth = 100;
00771     }
00772 #endif
00773     client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
00774 
00775     // set model
00776     if( g_gametype.integer >= GT_TEAM ) {
00777         Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) );
00778         Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) );
00779     } else {
00780         Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
00781         Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) );
00782     }
00783 
00784     // bots set their team a few frames later
00785     if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) {
00786         s = Info_ValueForKey( userinfo, "team" );
00787         if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
00788             team = TEAM_RED;
00789         } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
00790             team = TEAM_BLUE;
00791         } else {
00792             // pick the team with the least number of players
00793             team = PickTeam( clientNum );
00794         }
00795     }
00796     else {
00797         team = client->sess.sessionTeam;
00798     }
00799 
00800 /*  NOTE: all client side now
00801 
00802     // team
00803     switch( team ) {
00804     case TEAM_RED:
00805         ForceClientSkin(client, model, "red");
00806 //      ForceClientSkin(client, headModel, "red");
00807         break;
00808     case TEAM_BLUE:
00809         ForceClientSkin(client, model, "blue");
00810 //      ForceClientSkin(client, headModel, "blue");
00811         break;
00812     }
00813     // don't ever use a default skin in teamplay, it would just waste memory
00814     // however bots will always join a team but they spawn in as spectator
00815     if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) {
00816         ForceClientSkin(client, model, "red");
00817 //      ForceClientSkin(client, headModel, "red");
00818     }
00819 */
00820 
00821 #ifdef MISSIONPACK
00822     if (g_gametype.integer >= GT_TEAM) {
00823         client->pers.teamInfo = qtrue;
00824     } else {
00825         s = Info_ValueForKey( userinfo, "teamoverlay" );
00826         if ( ! *s || atoi( s ) != 0 ) {
00827             client->pers.teamInfo = qtrue;
00828         } else {
00829             client->pers.teamInfo = qfalse;
00830         }
00831     }
00832 #else
00833     // teamInfo
00834     s = Info_ValueForKey( userinfo, "teamoverlay" );
00835     if ( ! *s || atoi( s ) != 0 ) {
00836         client->pers.teamInfo = qtrue;
00837     } else {
00838         client->pers.teamInfo = qfalse;
00839     }
00840 #endif
00841     /*
00842     s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
00843     if ( !*s || atoi( s ) == 0 ) {
00844         client->pers.pmoveFixed = qfalse;
00845     }
00846     else {
00847         client->pers.pmoveFixed = qtrue;
00848     }
00849     */
00850 
00851     // team task (0 = none, 1 = offence, 2 = defence)
00852     teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
00853     // team Leader (1 = leader, 0 is normal player)
00854     teamLeader = client->sess.teamLeader;
00855 
00856     // colors
00857     strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
00858     strcpy(c2, Info_ValueForKey( userinfo, "color2" ));
00859 
00860     strcpy(redTeam, Info_ValueForKey( userinfo, "g_redteam" ));
00861     strcpy(blueTeam, Info_ValueForKey( userinfo, "g_blueteam" ));
00862 
00863     // send over a subset of the userinfo keys so other clients can
00864     // print scoreboards, display models, and play custom sounds
00865     if ( ent->r.svFlags & SVF_BOT ) {
00866         s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
00867             client->pers.netname, team, model, headModel, c1, c2, 
00868             client->pers.maxHealth, client->sess.wins, client->sess.losses,
00869             Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader );
00870     } else {
00871         s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\g_redteam\\%s\\g_blueteam\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
00872             client->pers.netname, client->sess.sessionTeam, model, headModel, redTeam, blueTeam, c1, c2, 
00873             client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, teamLeader);
00874     }
00875 
00876     trap_SetConfigstring( CS_PLAYERS+clientNum, s );
00877 
00878     // this is not the userinfo, more like the configstring actually
00879     G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
00880 }

Here is the call graph for this function:

void CopyToBodyQue gentity_t ent  ) 
 

Definition at line 369 of file g_client.c.

References entityShared_t::absmax, entityShared_t::absmin, gentity_s::activator, level_locals_t::bodyQue, level_locals_t::bodyQueIndex, BOTH_DEAD1, BOTH_DEAD2, BOTH_DEAD3, BOTH_DEATH1, BOTH_DEATH2, BOTH_DEATH3, gentity_s::classname, gentity_s::client, gentity_s::clipmask, entityShared_t::contents, CONTENTS_SOLID, entityShared_t::currentOrigin, gentity_s::die, e, entityState_s::eFlags, entityState_s::event, g_entities, gentity_t, entityState_s::groundEntityNum, gentity_s::health, i, gentity_s::inuse, entityState_s::legsAnim, level, entityState_s::loopSound, entityShared_t::maxs, entityShared_t::mins, gentity_s::nextthink, entityState_s::number, entityState_s::origin, entityShared_t::ownerNum, gentity_s::physicsBounce, gentity_s::physicsObject, entityState_s::pos, entityState_s::powerups, gclient_s::ps, gentity_s::r, gentity_s::s, strcmp(), entityShared_t::svFlags, gentity_s::takedamage, gentity_s::think, level_locals_t::time, gentity_s::timestamp, entityState_s::torsoAnim, trap_LinkEntity(), trap_PointContents(), trap_UnlinkEntity(), trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, VectorCopy, and playerState_s::velocity.

Referenced by respawn(), and SetTeam().

00369                                      {
00370 #ifdef MISSIONPACK
00371     gentity_t   *e;
00372     int i;
00373 #endif
00374     gentity_t       *body;
00375     int         contents;
00376 
00377     trap_UnlinkEntity (ent);
00378 
00379     // if client is in a nodrop area, don't leave the body
00380     contents = trap_PointContents( ent->s.origin, -1 );
00381     if ( contents & CONTENTS_NODROP ) {
00382         return;
00383     }
00384 
00385     // grab a body que and cycle to the next one
00386     body = level.bodyQue[ level.bodyQueIndex ];
00387     level.bodyQueIndex = (