codemp/game/g_client.c File Reference

#include "g_local.h"
#include "../ghoul2/G2.h"
#include "bg_saga.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define JMSABER_RESPAWN_TIME   20000
#define MAX_SPAWN_POINTS   128
#define MAX_SPAWN_POINTS   128
#define BODY_SINK_TIME   30000

Functions

void WP_SaberAddG2Model (gentity_t *saberent, const char *saberModel, qhandle_t saberSkin)
void WP_SaberRemoveG2Model (gentity_t *saberent)
qboolean WP_SaberStyleValidForSaber (saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int saberAnimLevel)
qboolean WP_UseFirstValidSaberStyle (saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int *saberAnimLevel)
void SP_info_player_duel (gentity_t *ent)
void SP_info_player_duel1 (gentity_t *ent)
void SP_info_player_duel2 (gentity_t *ent)
void SP_info_player_deathmatch (gentity_t *ent)
void SP_info_player_start (gentity_t *ent)
void SP_info_player_start_red (gentity_t *ent)
void SP_info_player_start_blue (gentity_t *ent)
void SiegePointUse (gentity_t *self, gentity_t *other, gentity_t *activator)
void SP_info_player_siegeteam1 (gentity_t *ent)
void SP_info_player_siegeteam2 (gentity_t *ent)
void SP_info_player_intermission (gentity_t *ent)
void SP_info_player_intermission_red (gentity_t *ent)
void SP_info_player_intermission_blue (gentity_t *ent)
void ThrowSaberToAttacker (gentity_t *self, gentity_t *attacker)
void JMSaberThink (gentity_t *ent)
void JMSaberTouch (gentity_t *self, gentity_t *other, trace_t *trace)
void SP_info_jedimaster_start (gentity_t *ent)
qboolean SpotWouldTelefrag (gentity_t *spot)
qboolean SpotWouldTelefrag2 (gentity_t *mover, vec3_t dest)
gentity_tSelectNearestDeathmatchSpawnPoint (vec3_t from)
gentity_tSelectRandomDeathmatchSpawnPoint (void)
gentity_tSelectRandomFurthestSpawnPoint (vec3_t avoidPoint, vec3_t origin, vec3_t angles, team_t team)
gentity_tSelectDuelSpawnPoint (int team, vec3_t avoidPoint, vec3_t origin, vec3_t angles)
gentity_tSelectSpawnPoint (vec3_t avoidPoint, vec3_t origin, vec3_t angles, team_t team)
gentity_tSelectInitialSpawnPoint (vec3_t origin, vec3_t angles, team_t team)
gentity_tSelectSpectatorSpawnPoint (vec3_t origin, vec3_t angles)
void InitBodyQue (void)
void BodySink (gentity_t *ent)
void SetClientViewAngle (gentity_t *ent, vec3_t angle)
void MaintainBodyQueue (gentity_t *ent)
void SiegeRespawn (gentity_t *ent)
void respawn (gentity_t *ent)
team_t TeamCount (int ignoreClientNum, int team)
int TeamLeader (int team)
team_t PickTeam (int ignoreClientNum)
qboolean G_SaberModelSetup (gentity_t *ent)
qboolean BG_IsValidCharacterModel (const char *modelName, const char *skinName)
qboolean BG_ValidateSkinForTeam (const char *modelName, char *skinName, int team, float *colors)
void BG_GetVehicleModelName (char *modelname)
void SetupGameGhoul2Model (gentity_t *ent, char *modelname, char *skinName)
qboolean G_SetSaber (gentity_t *ent, int saberNum, char *saberName, qboolean siegeOverride)
void G_ValidateSiegeClassForTeam (gentity_t *ent, int team)
void ClientUserinfoChanged (int clientNum)
char * ClientConnect (int clientNum, qboolean firstTime, qboolean isBot)
void G_WriteClientSessionData (gclient_t *client)
void WP_SetSaber (int entNum, saberInfo_t *sabers, int saberNum, const char *saberName)
void SetTeamQuick (gentity_t *ent, int team, qboolean doBegin)
void ClientBegin (int clientNum, qboolean allowTeamReset)
void G_BreakArm (gentity_t *ent, int arm)
qboolean BG_SaberStanceAnim (int anim)
qboolean PM_RunningAnim (int anim)
void G_UpdateClientAnims (gentity_t *self, float animSpeedScale)
qboolean WP_HasForcePowers (const playerState_t *ps)
void ClientSpawn (gentity_t *ent)
void ClientDisconnect (int clientNum)

Variables

int g_siegeRespawnCheck
forcedata_t Client_Force [MAX_CLIENTS]
gentity_tgJMSaberEnt = NULL
void * g2SaberInstance = NULL
qboolean gSiegeRoundBegun
qboolean gSiegeRoundEnded


Define Documentation

#define BODY_SINK_TIME   30000
 

Definition at line 946 of file g_client.c.

Referenced by BodySink().

#define JMSABER_RESPAWN_TIME   20000
 

Definition at line 256 of file g_client.c.

Referenced by JMSaberThink(), and JMSaberTouch().

#define MAX_SPAWN_POINTS   128
 

Definition at line 621 of file g_client.c.

#define MAX_SPAWN_POINTS   128
 

Definition at line 621 of file g_client.c.

Referenced by SelectRandomDeathmatchSpawnPoint().


Function Documentation

void BG_GetVehicleModelName char *  modelname  ) 
 

Definition at line 1599 of file bg_vehicleLoad.c.

References BG_VehicleGetIndex(), Com_Error(), ERR_DROP, g_vehicleInfo, strcpy(), and VEHICLE_NONE.

Referenced by CG_CacheG2AnimInfo(), CG_G2AnimEntModelLoad(), and SetupGameGhoul2Model().

01600 {
01601         char *vehName = &modelname[1];
01602         int vIndex = BG_VehicleGetIndex(vehName);
01603         assert(modelname[0] == '$');
01604         
01605         if (vIndex == VEHICLE_NONE)
01606         {
01607                 Com_Error(ERR_DROP, "BG_GetVehicleModelName:  couldn't find vehicle %s", vehName);
01608         }
01609 
01610     strcpy(modelname, g_vehicleInfo[vIndex].model);     
01611 }

qboolean BG_IsValidCharacterModel const char *  modelName,
const char *  skinName
 

Definition at line 2744 of file bg_misc.c.

References Q_stricmp(), qboolean, qfalse, and qtrue.

Referenced by BG_ValidateSkinForTeam(), and SetupGameGhoul2Model().

02745 {
02746         if (!Q_stricmp(skinName, "menu"))
02747         {
02748                 return qfalse;
02749         }
02750         else if (!Q_stricmp(modelName, "kyle"))
02751         {
02752                 if (!Q_stricmp(skinName, "fpls"))
02753                 {
02754                         return qfalse;
02755                 }
02756                 else if (!Q_stricmp(skinName, "fpls2"))
02757                 {
02758                         return qfalse;
02759                 }
02760                 else if (!Q_stricmp(skinName, "fpls3"))
02761                 {
02762                         return qfalse;
02763                 }
02764         }
02765         return qtrue;
02766 }

qboolean BG_SaberStanceAnim int  anim  ) 
 

Definition at line 33 of file bg_panimate.c.

References BOTH_SABERDUAL_STANCE, BOTH_SABERFAST_STANCE, BOTH_SABERSLOW_STANCE, BOTH_SABERSTAFF_STANCE, BOTH_STAND1, BOTH_STAND2, qboolean, qfalse, and qtrue.

Referenced by G_UpdateClientAnims().

00034 {
00035         switch ( anim )
00036         {
00037         case BOTH_STAND1://not really a saberstance anim, actually... "saber off" stance
00038         case BOTH_STAND2://single-saber, medium style
00039         case BOTH_SABERFAST_STANCE://single-saber, fast style
00040         case BOTH_SABERSLOW_STANCE://single-saber, strong style
00041         case BOTH_SABERSTAFF_STANCE://saber staff style
00042         case BOTH_SABERDUAL_STANCE://dual saber style
00043                 return qtrue;
00044                 break;
00045         }
00046         return qfalse;
00047 }

qboolean BG_ValidateSkinForTeam const char *  modelName,
char *  skinName,
int  team,
float *  colors
 

Definition at line 2768 of file bg_misc.c.

References BG_FileExists(), BG_IsValidCharacterModel(), MAX_QPATH, Q_strcat(), Q_stricmp(), Q_stricmpn(), Q_strncmp(), Q_strncpyz(), qboolean, qfalse, qtrue, strchr(), strlen(), TEAM_BLUE, TEAM_RED, and va().

Referenced by CG_NewClientInfo(), and SetupGameGhoul2Model().

02769 {
02770         if (!Q_stricmpn(modelName, "jedi_",5))
02771         { //argh, it's a custom player skin!
02772                 if (team == TEAM_RED && colors)
02773                 {
02774                         colors[0] = 1.0f;
02775                         colors[1] = 0.0f;
02776                         colors[2] = 0.0f;
02777                 }
02778                 else if (team == TEAM_BLUE && colors)
02779                 {
02780                         colors[0] = 0.0f;
02781                         colors[1] = 0.0f;
02782                         colors[2] = 1.0f;
02783                 }
02784                 return qtrue;
02785         }
02786 
02787         if (team == TEAM_RED)
02788         {
02789                 if ( Q_stricmp( "red", skinName ) != 0 )
02790                 {//not "red"
02791                         if ( Q_stricmp( "blue", skinName ) == 0
02792                                 || Q_stricmp( "default", skinName ) == 0
02793                                 || strchr(skinName, '|')//a multi-skin playerModel
02794                                 || !BG_IsValidCharacterModel(modelName, skinName) )
02795                         {
02796                                 Q_strncpyz(skinName, "red", MAX_QPATH);
02797                                 return qfalse;
02798                         }
02799                         else
02800                         {//need to set it to red
02801                                 int len = strlen( skinName );
02802                                 if ( len < 3 )
02803                                 {//too short to be "red"
02804                                         Q_strcat(skinName, MAX_QPATH, "_red");
02805                                 }
02806                                 else
02807                                 {
02808                                         char    *start = &skinName[len-3];
02809                                         if ( Q_strncmp( "red", start, 3 ) != 0 )
02810                                         {//doesn't already end in "red"
02811                                                 if ( len+4 >= MAX_QPATH )
02812                                                 {//too big to append "_red"
02813                                                         Q_strncpyz(skinName, "red", MAX_QPATH);
02814                                                         return qfalse;
02815                                                 }
02816                                                 else
02817                                                 {
02818                                                         Q_strcat(skinName, MAX_QPATH, "_red");
02819                                                 }
02820                                         }
02821                                 }
02822                                 //if file does not exist, set to "red"
02823                                 if ( !BG_FileExists( va( "models/players/%s/model_%s.skin", modelName, skinName ) ) )
02824                                 {
02825                                         Q_strncpyz(skinName, "red", MAX_QPATH);
02826                                 }
02827                                 return qfalse;
02828                         }
02829                 }
02830 
02831         }
02832         else if (team == TEAM_BLUE)
02833         {
02834                 if ( Q_stricmp( "blue", skinName ) != 0 )
02835                 {
02836                         if ( Q_stricmp( "red", skinName ) == 0
02837                                 || Q_stricmp( "default", skinName ) == 0
02838                                 || strchr(skinName, '|')//a multi-skin playerModel
02839                                 || !BG_IsValidCharacterModel(modelName, skinName) )
02840                         {
02841                                 Q_strncpyz(skinName, "blue", MAX_QPATH);
02842                                 return qfalse;
02843                         }
02844                         else
02845                         {//need to set it to blue
02846                                 int len = strlen( skinName );
02847                                 if ( len < 4 )
02848                                 {//too short to be "blue"
02849                                         Q_strcat(skinName, MAX_QPATH, "_blue");
02850                                 }
02851                                 else 
02852                                 {
02853                                         char    *start = &skinName[len-4];
02854                                         if ( Q_strncmp( "blue", start, 4 ) != 0 )
02855                                         {//doesn't already end in "blue"
02856                                                 if ( len+5 >= MAX_QPATH )
02857                                                 {//too big to append "_blue"
02858                                                         Q_strncpyz(skinName, "blue", MAX_QPATH);
02859                                                         return qfalse;
02860                                                 }
02861                                                 else
02862                                                 {
02863                                                         Q_strcat(skinName, MAX_QPATH, "_blue");
02864                                                 }
02865                                         }
02866                                 }
02867                                 //if file does not exist, set to "blue"
02868                                 if ( !BG_FileExists( va( "models/players/%s/model_%s.skin", modelName, skinName ) ) )
02869                                 {
02870                                         Q_strncpyz(skinName, "blue", MAX_QPATH);
02871                                 }
02872                                 return qfalse;
02873                         }
02874                 }
02875         }
02876         return qtrue;
02877 }

void BodySink gentity_t ent  ) 
 

Definition at line 973 of file g_client.c.

References BODY_SINK_TIME, EV_BODYFADE, G_AddEvent(), gentity_t, level, gentity_s::nextthink, gentity_s::physicsObject, qfalse, gentity_s::takedamage, level_locals_t::time, gentity_s::timestamp, and trap_UnlinkEntity().

00973                                 {
00974         if ( level.time - ent->timestamp > BODY_SINK_TIME + 2500 ) {
00975                 // the body ques are never actually freed, they are just unlinked
00976                 trap_UnlinkEntity( ent );
00977                 ent->physicsObject = qfalse;
00978                 return; 
00979         }
00980 //      ent->nextthink = level.time + 100;
00981 //      ent->s.pos.trBase[2] -= 1;
00982 
00983         G_AddEvent(ent, EV_BODYFADE, 0);
00984         ent->nextthink = level.time + 18000;
00985         ent->takedamage = qfalse;
00986 }

void ClientBegin int  clientNum,
qboolean  allowTeamReset
 

Definition at line 2385 of file g_client.c.

References CalculateRanks(), CHAN_VOICE, client, gentity_s::client, entityState_s::clientNum, level_locals_t::clients, ClientSpawn(), ClientUserinfoChanged(), CON_CONNECTED, clientPersistant_t::connected, clientSession_t::duelTeam, DUELTEAM_FREE, playerState_s::eFlags, clientPersistant_t::enterTime, EV_PLAYER_TELEPORT_IN, playerState_s::fd, forcedata_s::forcePowersActive, G_ClearClientLog(), g_entities, g_gametype, G_GetStringEdString(), G_InitGentity(), G_LogPrintf(), G_MuteSound(), G_ReadSessionData(), G_SetSaber(), G_TempEntity(), G_WriteClientSessionData(), gclient_t, gentity_t, gentity_s::ghoul2, gSiegeRoundBegun, gSiegeRoundEnded, GT_DUEL, GT_POWERDUEL, GT_SIEGE, GT_TEAM, playerState_s::hasDetPackPlanted, Info_SetValueForKey(), Info_ValueForKey(), vmCvar_t::integer, forcedata_s::killSoundEntIndex, renderInfo_s::lastG2, level, entityShared_t::linked, MAX_GENTITIES, MAX_INFO_STRING, MAX_INFO_VALUE, memset(), clientPersistant_t::netname, NULL, NUM_FORCE_POWERS, NUM_TRACK_CHANNELS, playerState_s::origin, gentity_s::pain, gclient_s::pers, PERS_TEAM, playerState_s::persistant, PickTeam(), gentity_s::playerState, gclient_s::ps, qfalse, gentity_s::r, rand(), gclient_s::renderInfo, gentity_s::s, S_COLOR_WHITE, gclient_s::sess, clientSession_t::sessionTeam, SetTeam(), SetTeamQuick(), SetupGameGhoul2Model(), playerTeamState_t::state, strcpy(), SVF_BOT, entityShared_t::svFlags, TEAM_BEGIN, TEAM_RED, TEAM_SPECTATOR, clientPersistant_t::teamState, level_locals_t::time, gentity_s::touch, TRACK_CHANNEL_1, trap_GetUserinfo(), trap_SendServerCommand(), trap_SetUserinfo(), trap_UnlinkEntity(), va(), WP_ForcePowerStop(), WP_InitForcePowers(), and WP_SaberInitBladeData().

Referenced by Cmd_SiegeClass_f(), G_CheckBotSpawn(), SetTeam(), SetTeamQuick(), SpectatorClientEndFrame(), and vmMain().

02385                                                            {
02386         gentity_t       *ent;
02387         gclient_t       *client;
02388         gentity_t       *tent;
02389         int                     flags, i;
02390         char            userinfo[MAX_INFO_VALUE], *modelname;
02391 
02392         ent = g_entities + clientNum;
02393 
02394         if ((ent->r.svFlags & SVF_BOT) && g_gametype.integer >= GT_TEAM)
02395         {
02396                 if (allowTeamReset)
02397                 {
02398                         const char *team = "Red";
02399                         int preSess;
02400 
02401                         //SetTeam(ent, "");
02402                         ent->client->sess.sessionTeam = PickTeam(-1);
02403                         trap_GetUserinfo(clientNum, userinfo, MAX_INFO_STRING);
02404 
02405                         if (ent->client->sess.sessionTeam == TEAM_SPECTATOR)
02406                         {
02407                                 ent->client->sess.sessionTeam = TEAM_RED;
02408                         }
02409 
02410                         if (ent->client->sess.sessionTeam == TEAM_RED)
02411                         {
02412                                 team = "Red";
02413                         }
02414                         else
02415                         {
02416                                 team = "Blue";
02417                         }
02418 
02419                         Info_SetValueForKey( userinfo, "team", team );
02420 
02421                         trap_SetUserinfo( clientNum, userinfo );
02422 
02423                         ent->client->ps.persistant[ PERS_TEAM ] = ent->client->sess.sessionTeam;
02424 
02425                         preSess = ent->client->sess.sessionTeam;
02426                         G_ReadSessionData( ent->client );
02427                         ent->client->sess.sessionTeam = preSess;
02428                         G_WriteClientSessionData(ent->client);
02429                         ClientUserinfoChanged( clientNum );
02430                         ClientBegin(clientNum, qfalse);
02431                         return;
02432                 }
02433         }
02434 
02435         client = level.clients + clientNum;
02436 
02437         if ( ent->r.linked ) {
02438                 trap_UnlinkEntity( ent );
02439         }
02440         G_InitGentity( ent );
02441         ent->touch = 0;
02442         ent->pain = 0;
02443         ent->client = client;
02444 
02445         //assign the pointer for bg entity access
02446         ent->playerState = &ent->client->ps;
02447 
02448         client->pers.connected = CON_CONNECTED;
02449         client->pers.enterTime = level.time;
02450         client->pers.teamState.state = TEAM_BEGIN;
02451 
02452         // save eflags around this, because changing teams will
02453         // cause this to happen with a valid entity, and we
02454         // want to make sure the teleport bit is set right
02455         // so the viewpoint doesn't interpolate through the
02456         // world to the new position
02457         flags = client->ps.eFlags;
02458 
02459         i = 0;
02460 
02461         while (i < NUM_FORCE_POWERS)
02462         {
02463                 if (ent->client->ps.fd.forcePowersActive & (1 << i))
02464                 {
02465                         WP_ForcePowerStop(ent, i);
02466                 }
02467                 i++;
02468         }
02469 
02470         i = TRACK_CHANNEL_1;
02471 
02472         while (i < NUM_TRACK_CHANNELS)
02473         {
02474                 if (ent->client->ps.fd.killSoundEntIndex[i-50] && ent->client->ps.fd.killSoundEntIndex[i-50] < MAX_GENTITIES && ent->client->ps.fd.killSoundEntIndex[i-50] > 0)
02475                 {
02476                         G_MuteSound(ent->client->ps.fd.killSoundEntIndex[i-50], CHAN_VOICE);
02477                 }
02478                 i++;
02479         }
02480         i = 0;
02481 
02482         memset( &client->ps, 0, sizeof( client->ps ) );
02483         client->ps.eFlags = flags;
02484 
02485         client->ps.hasDetPackPlanted = qfalse;
02486 
02487         //first-time force power initialization
02488         WP_InitForcePowers( ent );
02489 
02490         //init saber ent
02491         WP_SaberInitBladeData( ent );
02492 
02493         // First time model setup for that player.
02494         trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
02495         modelname = Info_ValueForKey (userinfo, "model");
02496         SetupGameGhoul2Model(ent, modelname, NULL);
02497 
02498         if (ent->ghoul2 && ent->client)
02499         {
02500                 ent->client->renderInfo.lastG2 = NULL; //update the renderinfo bolts next update.
02501         }
02502 
02503         if (g_gametype.integer == GT_POWERDUEL && client->sess.sessionTeam != TEAM_SPECTATOR &&
02504                 client->sess.duelTeam == DUELTEAM_FREE)
02505         {
02506                 SetTeam(ent, "s");
02507         }
02508         else
02509         {
02510                 if (g_gametype.integer == GT_SIEGE && (!gSiegeRoundBegun || gSiegeRoundEnded))
02511                 {
02512                         SetTeamQuick(ent, TEAM_SPECTATOR, qfalse);
02513                 }
02514         
02515                 if ((ent->r.svFlags & SVF_BOT) &&
02516                         g_gametype.integer != GT_SIEGE)
02517                 {
02518                         char *saberVal = Info_ValueForKey(userinfo, "saber1");
02519                         char *saber2Val = Info_ValueForKey(userinfo, "saber2");
02520 
02521                         if (!saberVal || !saberVal[0])
02522                         { //blah, set em up with a random saber
02523                                 int r = rand()%50;
02524                                 char sab1[1024];
02525                                 char sab2[1024];
02526 
02527                                 if (r <= 17)
02528                                 {
02529                                         strcpy(sab1, "Katarn");
02530                                         strcpy(sab2, "none");
02531                                 }
02532                                 else if (r <= 34)
02533                                 {
02534                                         strcpy(sab1, "Katarn");
02535                                         strcpy(sab2, "Katarn");
02536                                 }
02537                                 else
02538                                 {
02539                                         strcpy(sab1, "dual_1");
02540                                         strcpy(sab2, "none");
02541                                 }
02542                                 G_SetSaber(ent, 0, sab1, qfalse);
02543                                 G_SetSaber(ent, 0, sab2, qfalse);
02544                                 Info_SetValueForKey( userinfo, "saber1", sab1 );
02545                                 Info_SetValueForKey( userinfo, "saber2", sab2 );
02546                                 trap_SetUserinfo( clientNum, userinfo );
02547                         }
02548                         else
02549                         {
02550                                 G_SetSaber(ent, 0, saberVal, qfalse);
02551                         }
02552 
02553                         if (saberVal && saberVal[0] &&
02554                                 (!saber2Val || !saber2Val[0]))
02555                         {
02556                                 G_SetSaber(ent, 0, "none", qfalse);
02557                                 Info_SetValueForKey( userinfo, "saber2", "none" );
02558                                 trap_SetUserinfo( clientNum, userinfo );
02559                         }
02560                         else
02561                         {
02562                                 G_SetSaber(ent, 0, saber2Val, qfalse);
02563                         }
02564                 }
02565 
02566                 // locate ent at a spawn point
02567                 ClientSpawn( ent );
02568         }
02569 
02570         if ( client->sess.sessionTeam != TEAM_SPECTATOR ) {
02571                 // send event
02572                 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
02573                 tent->s.clientNum = ent->s.clientNum;
02574 
02575                 if ( g_gametype.integer != GT_DUEL || g_gametype.integer == GT_POWERDUEL ) {
02576                         trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s\n\"", client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLENTER")) );
02577                 }
02578         }
02579         G_LogPrintf( "ClientBegin: %i\n", clientNum );
02580 
02581         // count current clients and rank for scoreboard
02582         CalculateRanks();
02583 
02584         G_ClearClientLog(clientNum);
02585 }

char* ClientConnect int  clientNum,
qboolean  firstTime,
qboolean  isBot
 

Definition at line 2258 of file g_client.c.

References BroadcastTeamChange(), CalculateRanks(), client, gentity_s::client, level_locals_t::clients, ClientUserinfoChanged(), CON_CONNECTING, clientPersistant_t::connected, EV_CLIENTJOIN, entityState_s::eventParm, G_BotConnect(), g_entities, G_FilterPacket(), g_gametype, G_GetStringEdString(), G_InitSessionData(), G_LogPrintf(), g_needpass, g_password, G_ReadSessionData(), G_TempEntity(), gclient_t, gentity_t, GT_POWERDUEL, GT_SIEGE, GT_TEAM, Info_ValueForKey(), vmCvar_t::integer, gentity_s::inuse, level, MAX_INFO_STRING, memset(), clientPersistant_t::netname, level_locals_t::newSession, NULL, gclient_s::pers, gentity_s::playerState, gclient_s::ps, Q_stricmp(), Q_strncpyz(), qtrue, gentity_s::r, gentity_s::s, S_COLOR_WHITE, gclient_s::sess, clientSession_t::sessionTeam, clientSession_t::siegeDesiredTeam, strcmp(), vmCvar_t::string, SVF_BOT, SVF_BROADCAST, entityShared_t::svFlags, TEAM_SPECTATOR, trap_GetUserinfo(), trap_SendServerCommand(), va(), and vec3_origin.

Referenced by vmMain().

02258                                                                          {
02259         char            *value;
02260 //      char            *areabits;
02261         gclient_t       *client;
02262         char            userinfo[MAX_INFO_STRING];
02263         gentity_t       *ent;
02264         gentity_t       *te;
02265 
02266         ent = &g_entities[ clientNum ];
02267 
02268         trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );
02269 
02270         // check to see if they are on the banned IP list
02271         value = Info_ValueForKey (userinfo, "ip");
02272         if ( G_FilterPacket( value ) ) {
02273                 return "Banned.";
02274         }
02275 
02276         if ( !( ent->r.svFlags & SVF_BOT ) && !isBot && g_needpass.integer ) {
02277                 // check for a password
02278                 value = Info_ValueForKey (userinfo, "password");
02279                 if ( g_password.string[0] && Q_stricmp( g_password.string, "none" ) &&
02280                         strcmp( g_password.string, value) != 0) {
02281                         static char sTemp[1024];
02282                         Q_strncpyz(sTemp, G_GetStringEdString("MP_SVGAME","INVALID_ESCAPE_TO_MAIN"), sizeof (sTemp) );
02283                         return sTemp;// return "Invalid password";
02284                 }
02285         }
02286 
02287         // they can connect
02288         ent->client = level.clients + clientNum;
02289         client = ent->client;
02290 
02291         //assign the pointer for bg entity access
02292         ent->playerState = &ent->client->ps;
02293 
02294 //      areabits = client->areabits;
02295 
02296         memset( client, 0, sizeof(*client) );
02297 
02298         client->pers.connected = CON_CONNECTING;
02299 
02300         // read or initialize the session data
02301         if ( firstTime || level.newSession ) {
02302                 G_InitSessionData( client, userinfo, isBot );
02303         }
02304         G_ReadSessionData( client );
02305 
02306         if (g_gametype.integer == GT_SIEGE &&
02307                 (firstTime || level.newSession))
02308         { //if this is the first time then auto-assign a desired siege team and show briefing for that team
02309                 client->sess.siegeDesiredTeam = 0;//PickTeam(ent->s.number);
02310                 /*
02311                 trap_SendServerCommand(ent->s.number, va("sb %i", client->sess.siegeDesiredTeam));
02312                 */
02313                 //don't just show it - they'll see it if they switch to a team on purpose.
02314         }
02315 
02316 
02317         if (g_gametype.integer == GT_SIEGE && client->sess.sessionTeam != TEAM_SPECTATOR)
02318         {
02319                 if (firstTime || level.newSession)
02320                 { //start as spec
02321                         client->sess.siegeDesiredTeam = client->sess.sessionTeam;
02322                         client->sess.sessionTeam = TEAM_SPECTATOR;
02323                 }
02324         }
02325         else if (g_gametype.integer == GT_POWERDUEL && client->sess.sessionTeam != TEAM_SPECTATOR)
02326         {
02327                 client->sess.sessionTeam = TEAM_SPECTATOR;
02328         }
02329 
02330         if( isBot ) {
02331                 ent->r.svFlags |= SVF_BOT;
02332                 ent->inuse = qtrue;
02333                 if( !G_BotConnect( clientNum, !firstTime ) ) {
02334                         return "BotConnectfailed";
02335                 }
02336         }
02337 
02338         // get and distribute relevent paramters
02339         G_LogPrintf( "ClientConnect: %i\n", clientNum );
02340         ClientUserinfoChanged( clientNum );
02341 
02342         // don't do the "xxx connected" messages if they were caried over from previous level
02343         if ( firstTime ) {
02344                 trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s\n\"", client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLCONNECT")) );
02345         }
02346 
02347         if ( g_gametype.integer >= GT_TEAM &&
02348                 client->sess.sessionTeam != TEAM_SPECTATOR ) {
02349                 BroadcastTeamChange( client, -1 );
02350         }
02351 
02352         // count current clients and rank for scoreboard
02353         CalculateRanks();
02354 
02355         te = G_TempEntity( vec3_origin, EV_CLIENTJOIN );
02356         te->r.svFlags |= SVF_BROADCAST;
02357         te->s.eventParm = clientNum;
02358 
02359         // for statistics
02360 //      client->areabits = areabits;
02361 //      if ( !client->areabits )
02362 //              client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );
02363 
02364         return NULL;
02365 }

void ClientDisconnect int  clientNum  ) 
 

Definition at line 3808 of file g_client.c.

References bgEntity_t, BotAIShutdownClient(), CalculateRanks(), CHAN_VOICE, gentity_s::classname, gentity_s::client, entityState_s::clientNum, level_locals_t::clients, ClientUserinfoChanged(), CON_CONNECTED, CON_DISCONNECTED, clientPersistant_t::connected, entityShared_t::contents, CS_PLAYERS, vehicleInfo_t::Eject, EV_PLAYER_TELEPORT_OUT, playerState_s::fd, forcedata_s::forcePowersActive, G_ClearClientLog(), g_entities, g_gametype, G_LogPrintf(), G_MuteSound(), G_RemoveQueuedBotBegin(), G_TempEntity(), gentity_t, gentity_s::ghoul2, GT_DUEL, vmCvar_t::integer, level_locals_t::intermissiontime, gentity_s::inuse, forcedata_s::killSoundEntIndex, level, playerState_s::m_iVehicleNum, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MAX_GENTITIES, MAX_SABERS, level_locals_t::maxclients, entityState_s::modelindex, NUM_FORCE_POWERS, NUM_TRACK_CHANNELS, playerState_s::origin, gclient_s::pers, PERS_SCORE, PERS_TEAM, playerState_s::persistant, gclient_s::ps, qfalse, qtrue, 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(), SVF_BOT, entityShared_t::svFlags, TEAM_FREE, TEAM_SPECTATOR, TossClientItems(), TRACK_CHANNEL_1, trap_G2_HaveWeGhoul2Models(), trap_G2API_CleanGhoul2Models(), trap_SetConfigstring(), trap_UnlinkEntity(), level_locals_t::warmupTime, gclient_s::weaponGhoul2, and WP_ForcePowerStop().

Referenced by vmMain().

03808                                        {
03809         gentity_t       *ent;
03810         gentity_t       *tent;
03811         int                     i;
03812 
03813         // cleanup if we are kicking a bot that
03814         // hasn't spawned yet
03815         G_RemoveQueuedBotBegin( clientNum );
03816 
03817         ent = g_entities + clientNum;
03818         if ( !ent->client ) {
03819                 return;
03820         }
03821 
03822         i = 0;
03823 
03824         while (i < NUM_FORCE_POWERS)
03825         {
03826                 if (ent->client->ps.fd.forcePowersActive & (1 << i))
03827                 {
03828                         WP_ForcePowerStop(ent, i);
03829                 }
03830                 i++;
03831         }
03832 
03833         i = TRACK_CHANNEL_1;
03834 
03835         while (i < NUM_TRACK_CHANNELS)
03836         {
03837                 if (ent->client->ps.fd.killSoundEntIndex[i-50] && ent->client->ps.fd.killSoundEntIndex[i-50] < MAX_GENTITIES && ent->client->ps.fd.killSoundEntIndex[i-50] > 0)
03838                 {
03839                         G_MuteSound(ent->client->ps.fd.killSoundEntIndex[i-50], CHAN_VOICE);
03840                 }
03841                 i++;
03842         }
03843         i = 0;
03844 
03845         if (ent->client->ps.m_iVehicleNum)
03846         { //tell it I'm getting off
03847                 gentity_t *veh = &g_entities[ent->client->ps.m_iVehicleNum];
03848 
03849                 if (veh->inuse && veh->client && veh->m_pVehicle)
03850                 {
03851                         int pCon = ent->client->pers.connected;
03852 
03853                         ent->client->pers.connected = 0;
03854                         veh->m_pVehicle->m_pVehicleInfo->Eject(veh->m_pVehicle, (bgEntity_t *)ent, qtrue);
03855                         ent->client->pers.connected = pCon;
03856                 }
03857         }
03858 
03859         // stop any following clients
03860         for ( i = 0 ; i < level.maxclients ; i++ ) {
03861                 if ( level.clients[i].sess.sessionTeam == TEAM_SPECTATOR
03862                         && level.clients[i].sess.spectatorState == SPECTATOR_FOLLOW
03863                         && level.clients[i].sess.spectatorClient == clientNum ) {
03864                         StopFollowing( &g_entities[i] );
03865                 }
03866         }
03867 
03868         // send effect if they were completely connected
03869         if ( ent->client->pers.connected == CON_CONNECTED 
03870                 && ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
03871                 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
03872                 tent->s.clientNum = ent->s.clientNum;
03873 
03874                 // They don't get to take powerups with them!
03875                 // Especially important for stuff like CTF flags
03876                 TossClientItems( ent );
03877         }
03878 
03879         G_LogPrintf( "ClientDisconnect: %i\n", clientNum );
03880 
03881         // if we are playing in tourney mode, give a win to the other player and clear his frags for this round
03882         if ( (g_gametype.integer == GT_DUEL )
03883                 && !level.intermissiontime
03884                 && !level.warmupTime ) {
03885                 if ( level.sortedClients[1] == clientNum ) {
03886                         level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] = 0;
03887                         level.clients[ level.sortedClients[0] ].sess.wins++;
03888                         ClientUserinfoChanged( level.sortedClients[0] );
03889                 }
03890                 else if ( level.sortedClients[0] == clientNum ) {
03891                         level.clients[ level.sortedClients[1] ].ps.persistant[PERS_SCORE] = 0;
03892                         level.clients[ level.sortedClients[1] ].sess.wins++;
03893                         ClientUserinfoChanged( level.sortedClients[1] );
03894                 }
03895         }
03896 
03897         if (ent->ghoul2 && trap_G2_HaveWeGhoul2Models(ent->ghoul2))
03898         {
03899                 trap_G2API_CleanGhoul2Models(&ent->ghoul2);
03900         }
03901         i = 0;
03902         while (i < MAX_SABERS)
03903         {
03904                 if (ent->client->weaponGhoul2[i] && trap_G2_HaveWeGhoul2Models(ent->client->weaponGhoul2[i]))
03905                 {
03906                         trap_G2API_CleanGhoul2Models(&ent->client->weaponGhoul2[i]);
03907                 }
03908                 i++;
03909         }
03910 
03911         trap_UnlinkEntity (ent);
03912         ent->s.modelindex = 0;
03913         ent->inuse = qfalse;
03914         ent->classname = "disconnected";
03915         ent->client->pers.connected = CON_DISCONNECTED;
03916         ent->client->ps.persistant[PERS_TEAM] = TEAM_FREE;
03917         ent->client->sess.sessionTeam = TEAM_FREE;
03918         ent->r.contents = 0;
03919 
03920         trap_SetConfigstring( CS_PLAYERS + clientNum, "");
03921 
03922         CalculateRanks();
03923 
03924         if ( ent->r.svFlags & SVF_BOT ) {
03925                 BotAIShutdownClient( clientNum, qfalse );
03926         }
03927 
03928         G_ClearClientLog(clientNum);
03929 }

void ClientSpawn gentity_t ent  ) 
 

Definition at line 2930 of file g_client.c.

References gclient_s::accuracy_hits, gclient_s::accuracy_shots, gclient_s::airOutTime, playerState_s::ammo, AMMO_BLASTER, AMMO_POWERCELL, ammoData, weaponData_s::ammoIndex, atoi(), BG_PlayerStateToEntityState(), bgSiegeClasses, gclient_s::bodyGrabIndex, BOTH_STAND1TO2, CFL_EXTRA_AMMO, CFL_SINGLE_ROCKET, gentity_s::classname, client, gentity_s::client, ClientEndFrame(), playerState_s::clientNum, level_locals_t::clients, ClientThink(), ClientUserinfoChanged(), gentity_s::clipmask, playerState_s::cloakFuel, clientPersistant_t::cmd, playerState_s::commandTime, CON_DISCONNECTED, clientPersistant_t::connected, entityShared_t::contents, CONTENTS_BODY, CROUCH_MAXS_2, playerState_s::crouchheight, entityShared_t::currentOrigin, playerState_s::customRGBA, DEFAULT_MAXS_2, gentity_s::die, playerState_s::duelIndex, clientSession_t::duelTeam, DUELTEAM_LONE, DUELTEAM_SINGLE, EF_DOUBLE_AMMO, EF_INVULNERABLE, EF_TELEPORT_BIT, playerState_s::eFlags, gclient_s::enemyTeam, ENTITYNUM_NONE, playerState_s::eventSequence, playerState_s::fallingToDeath, playerState_s::fd, FL_NO_BOTS, FL_NO_HUMANS, gentity_s::flags, forcedata_t, forcedata_s::forceDoInit, forcedata_s::forcePowerLevel, FP_SABER_OFFENSE, g_duel_fraglimit, g_duelWeaponDisable, g_entities, g_forcePowerDisable, g_gametype, g_inactivity, G_KillBox(), g_powerDuelEndHealth, g_powerDuelStartHealth, G_SaberModelSetup(), G_SetAnim(), G_SetOrigin(), G_SetSaber(), g_spawnInvulnerability, g_trueJedi, G_UseTargets(), g_weaponDisable, gclient_t, playerState_s::genericEnemyIndex, gentity_t, entityState_s::groundEntityNum, GT_CTF, GT_CTY, GT_DUEL, GT_HOLOCRON, GT_JEDIMASTER, GT_POWERDUEL, GT_SIEGE, GT_TEAM, HasSetSaberOnly(), gentity_s::health, HL_MAX, gclient_s::inactivityTime, Info_SetValueForKey(), Info_ValueForKey(), clientPersistant_t::initialSpawn, vmCvar_t::integer, level_locals_t::intermissiontime, gentity_s::inuse, gclient_s::invulnerableTimer, playerState_s::isJediMaster, playerState_s::jetpackFuel, gclient_s::lastkilled_client, gclient_s::latched_buttons, playerState_s::legsAnim, playerState_s::legsTimer, level, clientPersistant_t::localClient, gentity_s::locationDamage, MASK_PLAYERSOLID, MAX_INFO_STRING, MAX_PERSISTANT, MAX_SABERS, level_locals_t::maxclients, siegeClass_t::maxhealth, clientPersistant_t::maxHealth, entityShared_t::maxs, memset(), gclient_s::mGameFlags, entityShared_t::mins, saberInfo_t::model, MoveClientToIntermission(), gclient_s::noCorpse, NPCTEAM_ENEMY, NPCTEAM_PLAYER, NULL, entityState_s::number, level_locals_t::numPlayingClients, playerState_s::origin, gclient_s::pers, PERS_SPAWN_COUNT, PERS_TEAM, playerState_s::persistant, playerState_s::ping, player_die(), playerMaxs, playerMins, gentity_s::playerState, gclient_s::playerTeam, playerState_s::pm_flags, playerState_s::pm_time, PMF_RESPAWNED, PMF_TIME_KNOCKBACK, playerState_s::powerups, gclient_s::ps, PSG_TEAMVOTED, PSG_VOTED, PW_NUM_POWERUPS, Q3_INFINITE, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::r, gclient_s::respawnTime, playerState_s::rocketLockIndex, playerState_s::rocketLockTime, gentity_s::s, gclient_s::saber, clientSession_t::saber2Type, forcedata_s::saberAnimLevel, forcedata_s::saberAnimLevelBase, gclient_s::saberCycleQueue, forcedata_s::saberDrawAnimLevel, playerState_s::saberEntityNum, saberInfo_t::saberFlags, playerState_s::saberHolstered, clientSession_t::saberLevel, gclient_s::saberStoredIndex, clientSession_t::saberType, SelectCTFSpawnPoint(), SelectDuelSpawnPoint(), SelectInitialSpawnPoint(), SelectSiegeSpawnPoint(), SelectSpawnPoint(), SelectSpectatorSpawnPoint(), usercmd_s::serverTime, gclient_s::sess, clientSession_t::sessionTeam, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_HOLDLESS, SETANIM_FLAG_OVERRIDE, SETANIM_TORSO, SetClientViewAngle(), SetTeam(), SFL_TWO_HANDED, gclient_s::siegeClass, SIEGETEAM_TEAM1, SS_DUAL, SS_FAST, SS_STAFF, SS_STRONG, playerState_s::standheight, STAT_ARMOR, STAT_HEALTH, STAT_HOLDABLE_ITEM, STAT_HOLDABLE_ITEMS, STAT_MAX_HEALTH, STAT_WEAPONS, playerTeamState_t::state, playerState_s::stats, SVF_BOT, entityShared_t::svFlags, gentity_s::takedamage, TEAM_ACTIVE, TEAM_BLUE, TEAM_RED, TEAM_SPECTATOR, TeamName(), entityState_s::teamowner, clientPersistant_t::teamState, level_locals_t::time, TORSO_RAISEWEAP1, playerState_s::torsoTimer, trap_Cvar_Set(), trap_GetUsercmd(), trap_GetUserinfo(), trap_ICARUS_FreeEnt(), trap_ICARUS_InitEnt(), trap_LinkEntity(), trap_SetUserinfo(), playerState_s::trueJedi, playerState_s::trueNonJedi, va(), vec3_t, VectorCopy, gentity_s::waterlevel, gentity_s::watertype, playerState_s::weapon, WEAPON_RAISING, weaponData, gclient_s::weaponGhoul2, WeaponReadyAnim, playerState_s::weaponstate, playerState_s::weaponTime, clientSession_t::wins, WP_BLASTER, WP_BOWCASTER, WP_BRYAR_PISTOL, WP_HasForcePowers(), WP_InitForcePowers(), WP_MELEE, WP_NONE, WP_NUM_WEAPONS, WP_ROCKET_LAUNCHER, WP_SABER, WP_SaberStyleValidForSaber(), WP_SpawnInitForcePowers(), and WP_UseFirstValidSaberStyle().

Referenced by ClientBegin(), G_ResetDuelists(), respawn(), and SiegeRespawn().

02930                                  {
02931         int                                     index;
02932         vec3_t                          spawn_origin, spawn_angles;
02933         gclient_t                       *client;
02934         int                                     i;
02935         clientPersistant_t      saved;
02936         clientSession_t         savedSess;
02937         int                                     persistant[MAX_PERSISTANT];
02938         gentity_t                       *spawnPoint;
02939         int                                     flags, gameFlags;
02940         int                                     savedPing;
02941         int                                     accuracy_hits, accuracy_shots;
02942         int                                     eventSequence;
02943         char                            userinfo[MAX_INFO_STRING];
02944         forcedata_t                     savedForce;
02945         int                                     saveSaberNum = ENTITYNUM_NONE;
02946         int                                     wDisable = 0;
02947         int                                     savedSiegeIndex = 0;
02948         int                                     maxHealth;
02949         saberInfo_t                     saberSaved[MAX_SABERS];
02950         int                                     l = 0;
02951         void                            *g2WeaponPtrs[MAX_SABERS];
02952         char                            *value;
02953         char                            *saber;
02954         qboolean                        changedSaber = qfalse;
02955         qboolean                        inSiegeWithClass = qfalse;
02956 
02957         index = ent - g_entities;
02958         client = ent->client;
02959 
02960         //first we want the userinfo so we can see if we should update this client's saber -rww
02961         trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
02962         while (l < MAX_SABERS)
02963         {
02964                 switch (l)
02965                 {
02966                 case 0:
02967                         saber = &ent->client->sess.saberType[0];
02968                         break;
02969                 case 1:
02970                         saber = &ent->client->sess.saber2Type[0];
02971                         break;
02972                 default:
02973                         saber = NULL;
02974                         break;
02975                 }
02976 
02977                 value = Info_ValueForKey (userinfo, va("saber%i", l+1));
02978                 if (saber &&
02979                         value &&
02980                         (Q_stricmp(value, saber) || !saber[0] || !ent->client->saber[0].model[0]))
02981                 { //doesn't match up (or our session saber is BS), we want to try setting it
02982                         if (G_SetSaber(ent, l, value, qfalse))
02983                         {
02984                                 changedSaber = qtrue;
02985                         }
02986                         else if (!saber[0] || !ent->client->saber[0].model[0])
02987                         { //Well, we still want to say they changed then (it means this is siege and we have some overrides)
02988                                 changedSaber = qtrue;
02989                         }
02990                 }
02991                 l++;
02992         }
02993 
02994         if (changedSaber)
02995         { //make sure our new info is sent out to all the other clients, and give us a valid stance
02996                 ClientUserinfoChanged( ent->s.number );
02997 
02998                 //make sure the saber models are updated
02999                 G_SaberModelSetup(ent);
03000 
03001                 l = 0;
03002                 while (l < MAX_SABERS)
03003                 { //go through and make sure both sabers match the userinfo
03004                         switch (l)
03005                         {
03006                         case 0:
03007                                 saber = &ent->client->sess.saberType[0];
03008                                 break;
03009                         case 1:
03010                                 saber = &ent->client->sess.saber2Type[0];
03011                                 break;
03012                         default:
03013                                 saber = NULL;
03014                                 break;
03015                         }
03016 
03017                         value = Info_ValueForKey (userinfo, va("saber%i", l+1));
03018 
03019                         if (Q_stricmp(value, saber))
03020                         { //they don't match up, force the user info
03021                                 Info_SetValueForKey(userinfo, va("saber%i", l+1), saber);
03022                                 trap_SetUserinfo( ent->s.number, userinfo );
03023                         }
03024                         l++;
03025                 }
03026 
03027                 if (ent->client->saber[0].model[0] &&
03028                         ent->client->saber[1].model[0])
03029                 { //dual
03030                         ent->client->ps.fd.saberAnimLevelBase = ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = SS_DUAL;
03031                 }
03032                 else if ((ent->client->saber[0].saberFlags&SFL_TWO_HANDED))
03033                 { //staff
03034                         ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = SS_STAFF;
03035                 }
03036                 else
03037                 {
03038                         if (ent->client->sess.saberLevel < SS_FAST)
03039                         {
03040                                 ent->client->sess.saberLevel = SS_FAST;
03041                         }
03042                         else if (ent->client->sess.saberLevel > SS_STRONG)
03043                         {
03044                                 ent->client->sess.saberLevel = SS_STRONG;
03045                         }
03046                         ent->client->ps.fd.saberAnimLevelBase = ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = ent->client->sess.saberLevel;
03047 
03048                         if (g_gametype.integer != GT_SIEGE &&
03049                                 ent->client->ps.fd.saberAnimLevel > ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
03050                         {
03051                                 ent->client->ps.fd.saberAnimLevelBase = ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = ent->client->sess.saberLevel = ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE];
03052                         }
03053                 }
03054                 if ( g_gametype.integer != GT_SIEGE )
03055                 {
03056                         //let's just make sure the styles we chose are cool
03057                         if ( !WP_SaberStyleValidForSaber( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, ent->client->ps.fd.saberAnimLevel ) )
03058                         {
03059                                 WP_UseFirstValidSaberStyle( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, &ent->client->ps.fd.saberAnimLevel );
03060                                 ent->client->ps.fd.saberAnimLevelBase = ent->client->saberCycleQueue = ent->client->ps.fd.saberAnimLevel;
03061                         }
03062                 }
03063         }
03064         l = 0;
03065 
03066         if (client->ps.fd.forceDoInit)
03067         { //force a reread of force powers
03068                 WP_InitForcePowers( ent );
03069                 client->ps.fd.forceDoInit = 0;
03070         }
03071 
03072         if (ent->client->ps.fd.saberAnimLevel != SS_STAFF &&
03073                 ent->client->ps.fd.saberAnimLevel != SS_DUAL &&
03074                 ent->client->ps.fd.saberAnimLevel == ent->client->ps.fd.saberDrawAnimLevel &&
03075                 ent->client->ps.fd.saberAnimLevel == ent->client->sess.saberLevel)
03076         {
03077                 if (ent->client->sess.saberLevel < SS_FAST)
03078                 {
03079                         ent->client->sess.saberLevel = SS_FAST;
03080                 }
03081                 else if (ent->client->sess.saberLevel > SS_STRONG)
03082                 {
03083                         ent->client->sess.saberLevel = SS_STRONG;
03084                 }
03085                 ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = ent->client->sess.saberLevel;
03086 
03087                 if (g_gametype.integer != GT_SIEGE &&
03088                         ent->client->ps.fd.saberAnimLevel > ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
03089                 {
03090                         ent->client->ps.fd.saberAnimLevel = ent->client->ps.fd.saberDrawAnimLevel = ent->client->sess.saberLevel = ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE];
03091                 }
03092         }
03093 
03094         // find a spawn point
03095         // do it before setting health back up, so farthest
03096         // ranging doesn't count this client
03097         if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
03098                 spawnPoint = SelectSpectatorSpawnPoint ( 
03099                                                 spawn_origin, spawn_angles);
03100         } else if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY) {
03101                 // all base oriented team games use the CTF spawn points
03102                 spawnPoint = SelectCTFSpawnPoint ( 
03103                                                 client->sess.sessionTeam, 
03104                                                 client->pers.teamState.state, 
03105                                                 spawn_origin, spawn_angles);
03106         }
03107         else if (g_gametype.integer == GT_SIEGE)
03108         {
03109                 spawnPoint = SelectSiegeSpawnPoint (
03110                                                 client->siegeClass,
03111                                                 client->sess.sessionTeam, 
03112                                                 client->pers.teamState.state, 
03113                                                 spawn_origin, spawn_angles);
03114         }
03115         else {
03116                 do {
03117                         if (g_gametype.integer == GT_POWERDUEL)
03118                         {
03119                                 spawnPoint = SelectDuelSpawnPoint(client->sess.duelTeam, client->ps.origin, spawn_origin, spawn_angles);
03120                         }
03121                         else if (g_gametype.integer == GT_DUEL)
03122                         {       // duel 
03123                                 spawnPoint = SelectDuelSpawnPoint(DUELTEAM_SINGLE, client->ps.origin, spawn_origin, spawn_angles);
03124                         }
03125                         else
03126                         {
03127                                 // the first spawn should be at a good looking spot
03128                                 if ( !client->pers.initialSpawn && client->pers.localClient ) {
03129                                         client->pers.initialSpawn = qtrue;
03130                                         spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles, client->sess.sessionTeam );
03131                                 } else {
03132                                         // don't spawn near existing origin if possible
03133                                         spawnPoint = SelectSpawnPoint ( 
03134                                                 client->ps.origin, 
03135                                                 spawn_origin, spawn_angles, client->sess.sessionTeam );
03136                                 }
03137                         }
03138 
03139                         // Tim needs to prevent bots from spawning at the initial point
03140                         // on q3dm0...
03141                         if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
03142                                 continue;       // try again
03143                         }
03144                         // just to be symetric, we have a nohumans option...
03145                         if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
03146                                 continue;       // try again
03147                         }
03148 
03149                         break;
03150 
03151                 } while ( 1 );
03152         }
03153         client->pers.teamState.state = TEAM_ACTIVE;
03154 
03155         // toggle the teleport bit so the client knows to not lerp
03156         // and never clear the voted flag
03157         flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT );
03158         flags ^= EF_TELEPORT_BIT;
03159         gameFlags = ent->client->mGameFlags & ( PSG_VOTED | PSG_TEAMVOTED);
03160 
03161         // clear everything but the persistant data
03162 
03163         saved = client->pers;
03164         savedSess = client->sess;
03165         savedPing = client->ps.ping;
03166 //      savedAreaBits = client->areabits;
03167         accuracy_hits = client->accuracy_hits;
03168         accuracy_shots = client->accuracy_shots;
03169         for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
03170                 persistant[i] = client->ps.persistant[i];
03171         }
03172         eventSequence = client->ps.eventSequence;
03173 
03174         savedForce = client->ps.fd;
03175 
03176         saveSaberNum = client->ps.saberEntityNum;
03177 
03178         savedSiegeIndex = client->siegeClass;
03179 
03180         l = 0;
03181         while (l < MAX_SABERS)
03182         {
03183                 saberSaved[l] = client->saber[l];
03184                 g2WeaponPtrs[l] = client->weaponGhoul2[l];
03185                 l++;
03186         }
03187 
03188         i = 0;
03189         while (i < HL_MAX)
03190         {
03191                 ent->locationDamage[i] = 0;
03192                 i++;
03193         }
03194 
03195         memset (client, 0, sizeof(*client)); // bk FIXME: Com_Memset?
03196         client->bodyGrabIndex = ENTITYNUM_NONE;
03197 
03198         //Get the skin RGB based on his userinfo
03199         value = Info_ValueForKey (userinfo, "char_color_red");
03200         if (value)
03201         {
03202                 client->ps.customRGBA[0] = atoi(value);
03203         }
03204         else
03205         {
03206                 client->ps.customRGBA[0] = 255;
03207         }
03208 
03209         value = Info_ValueForKey (userinfo, "char_color_green");
03210         if (value)
03211         {
03212                 client->ps.customRGBA[1] = atoi(value);
03213         }
03214         else
03215         {
03216                 client->ps.customRGBA[1] = 255;
03217         }
03218 
03219         value = Info_ValueForKey (userinfo, "char_color_blue");
03220         if (value)
03221         {
03222                 client->ps.customRGBA[2] = atoi(value);
03223         }
03224         else
03225         {
03226                 client->ps.customRGBA[2] = 255;
03227         }
03228 
03229         if ((client->ps.customRGBA[0]+client->ps.customRGBA[1]+client->ps.customRGBA[2]) < 100)
03230         { //hmm, too dark!
03231                 client->ps.customRGBA[0] = client->ps.customRGBA[1] = client->ps.customRGBA[2] = 255;
03232         }
03233 
03234         client->ps.customRGBA[3]=255;
03235 
03236         client->siegeClass = savedSiegeIndex;
03237 
03238         l = 0;
03239         while (l < MAX_SABERS)
03240         {
03241                 client->saber[l] = saberSaved[l];
03242                 client->weaponGhoul2[l] = g2WeaponPtrs[l];
03243                 l++;
03244         }
03245 
03246         //or the saber ent num
03247         client->ps.saberEntityNum = saveSaberNum;
03248         client->saberStoredIndex = saveSaberNum;
03249 
03250         client->ps.fd = savedForce;
03251 
03252         client->ps.duelIndex = ENTITYNUM_NONE;
03253 
03254         //spawn with 100
03255         client->ps.jetpackFuel = 100;
03256         client->ps.cloakFuel = 100;
03257 
03258         client->pers = saved;
03259         client->sess = savedSess;
03260         client->ps.ping = savedPing;
03261 //      client->areabits = savedAreaBits;
03262         client->accuracy_hits = accuracy_hits;
03263         client->accuracy_shots = accuracy_shots;
03264         client->lastkilled_client = -1;
03265 
03266         for ( i = 0 ; i < MAX_PERSISTANT ; i++ ) {
03267                 client->ps.persistant[i] = persistant[i];
03268         }
03269         client->ps.eventSequence = eventSequence;
03270         // increment the spawncount so the client will detect the respawn
03271         client->ps.persistant[PERS_SPAWN_COUNT]++;
03272         client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;
03273 
03274         client->airOutTime = level.time + 12000;
03275 
03276         // set max health
03277         if (g_gametype.integer == GT_SIEGE && client->siegeClass != -1)
03278         {
03279                 siegeClass_t *scl = &bgSiegeClasses[client->siegeClass];
03280                 maxHealth = 100;
03281 
03282                 if (scl->maxhealth)
03283                 {
03284                         maxHealth = scl->maxhealth;
03285                 }
03286         }
03287         else
03288         {
03289                 maxHealth = 100;
03290         }
03291         client->pers.maxHealth = maxHealth;//atoi( Info_ValueForKey( userinfo, "handicap" ) );
03292         if ( client->pers.maxHealth < 1 || client->pers.maxHealth > maxHealth ) {
03293                 client->pers.maxHealth = 100;
03294         }
03295         // clear entity values
03296         client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
03297         client->ps.eFlags = flags;
03298         client->mGameFlags = gameFlags;
03299 
03300         ent->s.groundEntityNum = ENTITYNUM_NONE;
03301         ent->client = &level.clients[index];
03302         ent->playerState = &ent->client->ps;
03303         ent->takedamage = qtrue;
03304         ent->inuse = qtrue;
03305         ent->classname = "player";
03306         ent->r.contents = CONTENTS_BODY;
03307         ent->clipmask = MASK_PLAYERSOLID;
03308         ent->die = player_die;
03309         ent->waterlevel = 0;
03310         ent->watertype = 0;
03311         ent->flags = 0;
03312         
03313         VectorCopy (playerMins, ent->r.mins);
03314         VectorCopy (playerMaxs, ent->r.maxs);
03315         client->ps.crouchheight = CROUCH_MAXS_2;
03316         client->ps.standheight = DEFAULT_MAXS_2;
03317 
03318         client->ps.clientNum = index;
03319         //give default weapons
03320         client->ps.stats[STAT_WEAPONS] = ( 1 << WP_NONE );
03321 
03322         if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
03323         {
03324                 wDisable = g_duelWeaponDisable.integer;
03325         }
03326         else
03327         {
03328                 wDisable = g_weaponDisable.integer;
03329         }
03330 
03331 
03332 
03333         if ( g_gametype.integer != GT_HOLOCRON 
03334                 && g_gametype.integer != GT_JEDIMASTER 
03335                 && !HasSetSaberOnly()
03336                 && !AllForceDisabled( g_forcePowerDisable.integer )
03337                 && g_trueJedi.integer )
03338         {
03339                 if ( g_gametype.integer >= GT_TEAM && (client->sess.sessionTeam == TEAM_BLUE || client->sess.sessionTeam == TEAM_RED) )
03340                 {//In Team games, force one side to be merc and other to be jedi
03341                         if ( level.numPlayingClients > 0 )
03342                         {//already someone in the game
03343                                 int             i, forceTeam = TEAM_SPECTATOR;
03344                                 for ( i = 0 ; i < level.maxclients ; i++ ) 
03345                                 {
03346                                         if ( level.clients[i].pers.connected == CON_DISCONNECTED ) {
03347                                                 continue;
03348                                         }
03349                                         if ( level.clients[i].sess.sessionTeam == TEAM_BLUE || level.clients[i].sess.sessionTeam == TEAM_RED ) 
03350                                         {//in-game
03351                                                 if ( WP_HasForcePowers( &level.clients[i].ps ) )
03352                                                 {//this side is using force
03353                                                         forceTeam = level.clients[i].sess.sessionTeam;
03354                                                 }
03355                                                 else
03356                                                 {//other team is using force
03357                                                         if ( level.clients[i].sess.sessionTeam == TEAM_BLUE )
03358                                                         {
03359                                                                 forceTeam = TEAM_RED;
03360                                                         }
03361                                                         else
03362                                                         {
03363                                                                 forceTeam = TEAM_BLUE;
03364                                                         }
03365                                                 }
03366                                                 break;
03367                                         }
03368                                 }
03369                                 if ( WP_HasForcePowers( &client->ps ) && client->sess.sessionTeam != forceTeam )
03370                                 {//using force but not on right team, switch him over
03371                                         const char *teamName = TeamName( forceTeam );
03372                                         //client->sess.sessionTeam = forceTeam;
03373                                         SetTeam( ent, (char *)teamName );
03374                                         return;
03375                                 }
03376                         }
03377                 }
03378 
03379                 if ( WP_HasForcePowers( &client->ps ) )
03380                 {
03381                         client->ps.trueNonJedi = qfalse;
03382                         client->ps.trueJedi = qtrue;
03383                         //make sure they only use the saber
03384                         client->ps.weapon = WP_SABER;
03385                         client->ps.stats[STAT_WEAPONS] = (1 << WP_SABER);
03386                 }
03387                 else
03388                 {//no force powers set
03389                         client->ps.trueNonJedi = qtrue;
03390                         client->ps.trueJedi = qfalse;
03391                         if (!wDisable || !(wDisable & (1 << WP_BRYAR_PISTOL)))
03392                         {
03393                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
03394                         }
03395                         if (!wDisable || !(wDisable & (1 << WP_BLASTER)))
03396                         {
03397                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BLASTER );
03398                         }
03399                         if (!wDisable || !(wDisable & (1 << WP_BOWCASTER)))
03400                         {
03401                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BOWCASTER );
03402                         }
03403                         client->ps.stats[STAT_WEAPONS] &= ~(1 << WP_SABER);
03404                         client->ps.stats[STAT_WEAPONS] |= (1 << WP_MELEE);
03405                         client->ps.ammo[AMMO_POWERCELL] = ammoData[AMMO_POWERCELL].max;
03406                         client->ps.weapon = WP_BRYAR_PISTOL;
03407                 }
03408         }
03409         else
03410         {//jediVmerc is incompatible with this gametype, turn it off!
03411                 trap_Cvar_Set( "g_jediVmerc", "0" );
03412                 if (g_gametype.integer == GT_HOLOCRON)
03413                 {
03414                         //always get free saber level 1 in holocron
03415                         client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_SABER );    //these are precached in g_items, ClearRegisteredItems()
03416                 }
03417                 else
03418                 {
03419                         if (client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE])
03420                         {
03421                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_SABER );    //these are precached in g_items, ClearRegisteredItems()
03422                         }
03423                         else
03424                         { //if you don't have saber attack rank then you don't get a saber
03425                                 client->ps.stats[STAT_WEAPONS] |= (1 << WP_MELEE);
03426                         }
03427                 }
03428 
03429                 if (g_gametype.integer != GT_SIEGE)
03430                 {
03431                         if (!wDisable || !(wDisable & (1 << WP_BRYAR_PISTOL)))
03432                         {
03433                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
03434                         }
03435                         else if (g_gametype.integer == GT_JEDIMASTER)
03436                         {
03437                                 client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL );
03438                         }
03439                 }
03440 
03441                 if (g_gametype.integer == GT_JEDIMASTER)
03442                 {
03443                         client->ps.stats[STAT_WEAPONS] &= ~(1 << WP_SABER);
03444                         client->ps.stats[STAT_WEAPONS] |= (1 << WP_MELEE);
03445                 }
03446 
03447                 if (client->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
03448                 {
03449                         client->ps.weapon = WP_SABER;
03450                 }
03451                 else if (client->ps.stats[STAT_WEAPONS] & (1 << WP_BRYAR_PISTOL))
03452                 {
03453                         client->ps.weapon = WP_BRYAR_PISTOL;
03454                 }
03455                 else
03456                 {
03457                         client->ps.weapon = WP_MELEE;
03458                 }
03459         }
03460 
03461         /*
03462         client->ps.stats[STAT_HOLDABLE_ITEMS] |= ( 1 << HI_BINOCULARS );
03463         client->ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_BINOCULARS, IT_HOLDABLE);
03464         */
03465 
03466         if (g_gametype.integer == GT_SIEGE && client->siegeClass != -1 &&
03467                 client->sess.sessionTeam != TEAM_SPECTATOR)
03468         { //well then, we will use a custom weaponset for our class
03469                 int m = 0;
03470 
03471                 client->ps.stats[STAT_WEAPONS] = bgSiegeClasses[client->siegeClass].weapons;
03472 
03473                 if (client->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
03474                 {
03475                         client->ps.weapon = WP_SABER;
03476                 }
03477                 else if (client->ps.stats[STAT_WEAPONS] & (1 << WP_BRYAR_PISTOL))
03478                 {
03479                         client->ps.weapon = WP_BRYAR_PISTOL;
03480                 }
03481                 else
03482                 {
03483                         client->ps.weapon = WP_MELEE;
03484                 }
03485                 inSiegeWithClass = qtrue;
03486 
03487                 while (m < WP_NUM_WEAPONS)
03488                 {
03489                         if (client->ps.stats[STAT_WEAPONS] & (1 << m))
03490                         {
03491                                 if (client->ps.weapon != WP_SABER)
03492                                 { //try to find the highest ranking weapon we have
03493                                         if (m > client->ps.weapon)
03494                                         {
03495                                                 client->ps.weapon = m;
03496                                         }
03497                                 }
03498 
03499                                 if (m >= WP_BRYAR_PISTOL)
03500                                 { //Max his ammo out for all the weapons he has.
03501                                         if ( g_gametype.integer == GT_SIEGE 
03502                                                 && m == WP_ROCKET_LAUNCHER )
03503                                         {//don't give full ammo!
03504                                                 //FIXME: extern this and check it when getting ammo from supplier, pickups or ammo stations!
03505                                                 if ( client->siegeClass != -1 &&
03506                                                         (bgSiegeClasses[client->siegeClass].classflags & (1<<CFL_SINGLE_ROCKET)) )
03507                                                 {
03508                                                         client->ps.ammo[weaponData[m].ammoIndex] = 1;
03509                                                 }
03510                                                 else
03511                                                 {
03512                                                         client->ps.ammo[weaponData[m].ammoIndex] = 10;
03513                                                 }
03514                                         }
03515                                         else
03516                                         {
03517                                                 if ( g_gametype.integer == GT_SIEGE 
03518                                                         && client->siegeClass != -1
03519                                                         && (bgSiegeClasses[client->siegeClass].classflags & (1<<CFL_EXTRA_AMMO)) )
03520                                                 {//double ammo
03521                                                         client->ps.ammo[weaponData[m].ammoIndex] = ammoData[weaponData[m].ammoIndex].max*2;
03522                                                         client->ps.eFlags |= EF_DOUBLE_AMMO;
03523                                                 }
03524                                                 else
03525                                                 {
03526                                                         client->ps.ammo[weaponData[m].ammoIndex] = ammoData[weaponData[m].ammoIndex].max;
03527                                                 }
03528                                         }
03529                                 }
03530                         }
03531                         m++;
03532                 }
03533         }
03534 
03535         if (g_gametype.integer == GT_SIEGE &&
03536                 client->siegeClass != -1 &&
03537                 client->sess.sessionTeam != TEAM_SPECTATOR)
03538         { //use class-specified inventory
03539                 client->ps.stats[STAT_HOLDABLE_ITEMS] = bgSiegeClasses[client->siegeClass].invenItems;
03540                 client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
03541         }
03542         else
03543         {
03544                 client->ps.stats[STAT_HOLDABLE_ITEMS] = 0;
03545                 client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
03546         }
03547 
03548         if (g_gametype.integer == GT_SIEGE &&
03549                 client->siegeClass != -1 &&
03550                 bgSiegeClasses[client->siegeClass].powerups &&
03551                 client->sess.sessionTeam != TEAM_SPECTATOR)
03552         { //this class has some start powerups
03553                 i = 0;
03554                 while (i < PW_NUM_POWERUPS)
03555                 {
03556                         if (bgSiegeClasses[client->siegeClass].powerups & (1 << i))
03557                         {
03558                                 client->ps.powerups[i] = Q3_INFINITE;
03559                         }
03560                         i++;
03561                 }
03562         }
03563 
03564         if ( client->sess.sessionTeam == TEAM_SPECTATOR )
03565         {
03566                 client->ps.stats[STAT_WEAPONS] = 0;
03567                 client->ps.stats[STAT_HOLDABLE_ITEMS] = 0;
03568                 client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
03569         }
03570 
03571 // nmckenzie: DESERT_SIEGE... or well, siege generally.  This was over-writing the max value, which was NOT good for siege.
03572         if ( inSiegeWithClass == qfalse )
03573         {
03574                 client->ps.ammo[AMMO_BLASTER] = 100; //ammoData[AMMO_BLASTER].max; //100 seems fair.
03575         }
03576 //      client->ps.ammo[AMMO_POWERCELL] = ammoData[AMMO_POWERCELL].max;
03577 //      client->ps.ammo[AMMO_FORCE] = ammoData[AMMO_FORCE].max;
03578 //      client->ps.ammo[AMMO_METAL_BOLTS] = ammoData[AMMO_METAL_BOLTS].max;
03579 //      client->ps.ammo[AMMO_ROCKETS] = ammoData[AMMO_ROCKETS].max;
03580 /*
03581         client->ps.stats[STAT_WEAPONS] = ( 1 << WP_BRYAR_PISTOL);
03582         if ( g_gametype.integer == GT_TEAM ) {
03583                 client->ps.ammo[WP_BRYAR_PISTOL] = 50;
03584         } else {
03585                 client->ps.ammo[WP_BRYAR_PISTOL] = 100;
03586         }
03587 */
03588         client->ps.rocketLockIndex = ENTITYNUM_NONE;
03589         client->ps.rocketLockTime = 0;
03590 
03591         //rww - Set here to initialize the circling seeker drone to off.
03592         //A quick note about this so I don't forget how it works again:
03593         //ps.genericEnemyIndex is kept in sync between the server and client.
03594         //When it gets set then an entitystate value of the same name gets
03595         //set along with an entitystate flag in the shared bg code. Which
03596         //is why a value needs to be both on the player state and entity state.
03597         //(it doesn't seem to just carry over the entitystate value automatically
03598         //because entity state value is derived from player state data or some
03599         //such)
03600         client->ps.genericEnemyIndex = -1;
03601 
03602         client->ps.isJediMaster = qfalse;
03603 
03604         if (client->ps.fallingToDeath)
03605         {
03606                 client->ps.fallingToDeath = 0;
03607                 client->noCorpse = qtrue;
03608         }
03609 
03610         //Do per-spawn force power initialization
03611         WP_SpawnInitForcePowers( ent );
03612 
03613         // health will count down towards max_health
03614         if (g_gametype.integer == GT_SIEGE &&
03615                 client->siegeClass != -1 &&
03616                 bgSiegeClasses[client->siegeClass].starthealth)
03617         { //class specifies a start health, so use it
03618                 ent->health = client->ps.stats[STAT_HEALTH] = bgSiegeClasses[client->siegeClass].starthealth;
03619         }
03620         else if ( g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL )
03621         {//only start with 100 health in Duel
03622                 if ( g_gametype.integer == GT_POWERDUEL && client->sess.duelTeam == DUELTEAM_LONE )
03623                 {
03624                         if ( g_duel_fraglimit.integer )
03625                         {
03626                                 
03627                                 ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] =
03628                                         g_powerDuelStartHealth.integer - ((g_powerDuelStartHealth.integer - g_powerDuelEndHealth.integer) * (float)client->sess.wins / (float)g_duel_fraglimit.integer);
03629                         }
03630                         else
03631                         {
03632                                 ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] = 150;
03633                         }
03634                 }
03635                 else
03636                 {
03637                         ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] = 100;
03638                 }
03639         }
03640         else if (client->ps.stats[STAT_MAX_HEALTH] <= 100)
03641         {
03642                 ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] * 1.25;
03643         }
03644         else if (client->ps.stats[STAT_MAX_HEALTH] < 125)
03645         {
03646                 ent->health = client->ps.stats[STAT_HEALTH] = 125;
03647         }
03648         else
03649         {
03650                 ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH];
03651         }
03652 
03653         // Start with a small amount of armor as well.
03654         if (g_gametype.integer == GT_SIEGE &&
03655                 client->siegeClass != -1 /*&&
03656                 bgSiegeClasses[client->siegeClass].startarmor*/)
03657         { //class specifies a start armor amount, so use it
03658                 client->ps.stats[STAT_ARMOR] = bgSiegeClasses[client->siegeClass].startarmor;
03659         }
03660         else if ( g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL )
03661         {//no armor in duel
03662                 client->ps.stats[STAT_ARMOR] = 0;
03663         }
03664         else
03665         {
03666                 client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH] * 0.25;
03667         }
03668 
03669         G_SetOrigin( ent, spawn_origin );
03670         VectorCopy( spawn_origin, client->ps.origin );
03671 
03672         // the respawned flag will be cleared after the attack and jump keys come up
03673         client->ps.pm_flags |= PMF_RESPAWNED;
03674 
03675         trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
03676         SetClientViewAngle( ent, spawn_angles );
03677 
03678         if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
03679 
03680         } else {
03681                 G_KillBox( ent );
03682                 trap_LinkEntity (ent);
03683 
03684                 // force the base weapon up
03685                 //client->ps.weapon = WP_BRYAR_PISTOL;
03686                 //client->ps.weaponstate = FIRST_WEAPON;
03687                 if (client->ps.weapon <= WP_NONE)
03688                 {
03689                         client->ps.weapon = WP_BRYAR_PISTOL;
03690                 }
03691 
03692                 client->ps.torsoTimer = client->ps.legsTimer = 0;
03693 
03694                 if (client->ps.weapon == WP_SABER)
03695                 {
03696                         G_SetAnim(ent, NULL, SETANIM_BOTH, BOTH_STAND1TO2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS, 0);
03697                 }
03698                 else
03699                 {
03700                         G_SetAnim(ent, NULL, SETANIM_TORSO, TORSO_RAISEWEAP1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS, 0);
03701                         client->ps.legsAnim = WeaponReadyAnim[client->ps.weapon];
03702                 }
03703                 client->ps.weaponstate = WEAPON_RAISING;
03704                 client->ps.weaponTime = client->ps.torsoTimer;
03705         }
03706 
03707         // don't allow full run speed for a bit
03708         client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
03709         client->ps.pm_time = 100;
03710 
03711         client->respawnTime = level.time;
03712         client->inactivityTime = level.time + g_inactivity.integer * 1000;
03713         client->latched_buttons = 0;
03714 
03715         if ( level.intermissiontime ) {
03716                 MoveClientToIntermission( ent );
03717         } else {
03718                 // fire the targets of the spawn point
03719                 G_UseTargets( spawnPoint, ent );
03720 
03721                 // select the highest weapon number available, after any
03722                 // spawn given items have fired
03723                 /*
03724                 client->ps.weapon = 1;
03725                 for ( i = WP_NUM_WEAPONS - 1 ; i > 0 ; i-- ) {
03726                         if ( client->ps.stats[STAT_WEAPONS] & ( 1 << i ) ) {
03727                                 client->ps.weapon = i;
03728                                 break;
03729                         }
03730                 }
03731                 */
03732         }
03733 
03734         //set teams for NPCs to recognize
03735         if (g_gametype.integer == GT_SIEGE)
03736         { //Imperial (team1) team is allied with "enemy" NPCs in this mode
03737                 if (client->sess.sessionTeam == SIEGETEAM_TEAM1)
03738                 {
03739                         client->playerTeam = ent->s.teamowner = NPCTEAM_ENEMY;
03740                         client->enemyTeam = NPCTEAM_PLAYER;
03741                 }
03742                 else
03743                 {
03744                         client->playerTeam = ent->s.teamowner = NPCTEAM_PLAYER;
03745                         client->enemyTeam = NPCTEAM_ENEMY;
03746                 }
03747         }
03748         else
03749         {
03750                 client->playerTeam = ent->s.teamowner = NPCTEAM_PLAYER;
03751                 client->enemyTeam = NPCTEAM_ENEMY;
03752         }
03753 
03754         /*
03755         //scaling for the power duel opponent
03756         if (g_gametype.integer == GT_POWERDUEL &&
03757                 client->sess.duelTeam == DUELTEAM_LONE)
03758         {
03759                 client->ps.iModelScale = 125;
03760                 VectorSet(ent->modelScale, 1.25f, 1.25f, 1.25f);
03761         }
03762         */
03763         //Disabled. At least for now. Not sure if I'll want to do it or not eventually.
03764 
03765         // run a client frame to drop exactly to the floor,
03766         // initialize animations and other things
03767         client->ps.commandTime = level.time - 100;
03768         ent->client->pers.cmd.serverTime = level.time;
03769         ClientThink( ent-g_entities, NULL );
03770 
03771         // positively link the client, even if the command times are weird
03772         if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
03773                 BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
03774                 VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
03775                 trap_LinkEntity( ent );
03776         }
03777 
03778         if (g_spawnInvulnerability.integer)
03779         {
03780                 ent->client->ps.eFlags |= EF_INVULNERABLE;
03781                 ent->client->invulnerableTimer = level.time + g_spawnInvulnerability.integer;
03782         }
03783 
03784         // run the presend to set anything else
03785         ClientEndFrame( ent );
03786 
03787         // clear entity state values
03788         BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
03789 
03790         //rww - make sure client has a valid icarus instance
03791         trap_ICARUS_FreeEnt( ent );
03792         trap_ICARUS_InitEnt( ent );
03793 }

void ClientUserinfoChanged int  clientNum  ) 
 

Definition at line 1888 of file g_client.c.

References atoi(), BG_SiegeCheckClassLegality(), BG_SiegeFindClassIndexByName(), bgSiegeClasses, client, gentity_s::client, CON_CONNECTED, clientPersistant_t::connected, CS_PLAYERS, playerState_s::customRGBA, d_perPlayerGhoul2, clientSession_t::duelTeam, siegeClass_t::forcedModel, g_entities, g_gametype, G_GetStringEdString(), g_logClientInfo, G_LogPrintf(), G_PlayerHasCustomSkeleton(), G_SaberModelSetup(), G_SetSaber(), G_ValidateSiegeClassForTeam(), gclient_t, gentity_t, gentity_s::ghoul2, GT_SIEGE, GT_TEAM, Info_SetValueForKey(), Info_Validate(), Info_ValueForKey(), vmCvar_t::integer, renderInfo_s::lastG2, gclient_s::legsAnimExecute, gclient_s::legsLastFlip, level, gentity_s::localAnimIndex, clientPersistant_t::localClient, clientSession_t::losses, MAX_INFO_STRING, MAX_QPATH, MAX_STRING_CHARS, siegeClass_t::maxhealth, clientPersistant_t::maxHealth, gclient_s::modelname, clientPersistant_t::netname, clientPersistant_t::netnameTime, NULL, gclient_s::pers, PickTeam(), clientPersistant_t::predictItemPickup, gclient_s::ps, Q_stricmp(), Q_strncpyz(), qboolean, qfalse, qtrue, gentity_s::r, gclient_s::renderInfo, S_COLOR_WHITE, siegeClass_t::saber1, siegeClass_t::saber2, clientSession_t::saber2Type, clientSession_t::saberType, gclient_s::sess, clientSession_t::sessionTeam, SetupGameGhoul2Model(), clientSession_t::siegeClass, gclient_s::siegeClass, clientSession_t::siegeDesiredTeam, SPECTATOR_SCOREBOARD, clientSession_t::spectatorState, STAT_MAX_HEALTH, playerState_s::stats, strcmp(), strcpy(), SVF_BOT, entityShared_t::svFlags, TEAM_BLUE, TEAM_RED, TEAM_SPECTATOR, clientPersistant_t::teamInfo, clientSession_t::teamLeader, level_locals_t::time, gclient_s::torsoAnimExecute, gclient_s::torsoLastFlip, trap_GetUserinfo(), trap_SendServerCommand(), trap_SetConfigstring(), trap_SetUserinfo(), va(), and clientSession_t::wins.

Referenced by AdjustTournamentScores(), ClientBegin(), ClientConnect(), ClientDisconnect(), ClientSpawn(), Cmd_DuelTeam_f(), Cmd_SiegeClass_f(), Cmd_TeamTask_f(), G_AddPowerDuelLoserScore(), G_AddPowerDuelScore(), SetLeader(), SetTeam(), SetTeamQuick(), and vmMain().

01888                                             {
01889         gentity_t *ent;
01890         int             teamTask, teamLeader, team, health;
01891         char    *s;
01892         char    model[MAX_QPATH];
01893         //char  headModel[MAX_QPATH];
01894         char    forcePowers[MAX_QPATH];
01895         char    oldname[MAX_STRING_CHARS];
01896         gclient_t       *client;
01897         char    c1[MAX_INFO_STRING];
01898         char    c2[MAX_INFO_STRING];
01899 //      char    redTeam[MAX_INFO_STRING];
01900 //      char    blueTeam[MAX_INFO_STRING];
01901         char    userinfo[MAX_INFO_STRING];
01902         char    className[MAX_QPATH]; //name of class type to use in siege
01903         char    saberName[MAX_QPATH];
01904         char    saber2Name[MAX_QPATH];
01905         char    *value;
01906         int             maxHealth;
01907         qboolean        modelChanged = qfalse;
01908 
01909         ent = g_entities + clientNum;
01910         client = ent->client;
01911 
01912         trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );
01913 
01914         // check for malformed or illegal info strings
01915         if ( !Info_Validate(userinfo) ) {
01916                 strcpy (userinfo, "\\name\\badinfo");
01917         }
01918 
01919         // check for local client
01920         s = Info_ValueForKey( userinfo, "ip" );
01921         if ( !strcmp( s, "localhost" ) ) {
01922                 client->pers.localClient = qtrue;
01923         }
01924 
01925         // check the item prediction
01926         s = Info_ValueForKey( userinfo, "cg_predictItems" );
01927         if ( !atoi( s ) ) {
01928                 client->pers.predictItemPickup = qfalse;
01929         } else {
01930                 client->pers.predictItemPickup = qtrue;
01931         }
01932 
01933         // set name
01934         Q_strncpyz ( oldname, client->pers.netname, sizeof( oldname ) );
01935         s = Info_ValueForKey (userinfo, "name");
01936         ClientCleanName( s, client->pers.netname, sizeof(client->pers.netname) );
01937 
01938         if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
01939                 if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
01940                         Q_strncpyz( client->pers.netname, "scoreboard", sizeof(client->pers.netname) );
01941                 }
01942         }
01943 
01944         if ( client->pers.connected == CON_CONNECTED ) {
01945                 if ( strcmp( oldname, client->pers.netname ) ) 
01946                 {
01947                         if ( client->pers.netnameTime > level.time  )
01948                         {
01949                                 trap_SendServerCommand( clientNum, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NONAMECHANGE")) );
01950 
01951                                 Info_SetValueForKey( userinfo, "name", oldname );
01952                                 trap_SetUserinfo( clientNum, userinfo );                        
01953                                 strcpy ( client->pers.netname, oldname );
01954                         }
01955                         else
01956                         {                               
01957                                 trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s %s\n\"", oldname, G_GetStringEdString("MP_SVGAME", "PLRENAME"), client->pers.netname) );
01958                                 client->pers.netnameTime = level.time + 5000;
01959                         }
01960                 }
01961         }
01962 
01963         // set model
01964         Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
01965 
01966         if (d_perPlayerGhoul2.integer)
01967         {
01968                 if (Q_stricmp(model, client->modelname))
01969                 {
01970                         strcpy(client->modelname, model);
01971                         modelChanged = qtrue;
01972                 }
01973         }
01974 
01975         //Get the skin RGB based on his userinfo
01976         value = Info_ValueForKey (userinfo, "char_color_red");
01977         if (value)
01978         {
01979                 client->ps.customRGBA[0] = atoi(value);
01980         }
01981         else
01982         {
01983                 client->ps.customRGBA[0] = 255;
01984         }
01985 
01986         value = Info_ValueForKey (userinfo, "char_color_green");
01987         if (value)
01988         {
01989                 client->ps.customRGBA[1] = atoi(value);
01990         }
01991         else
01992         {
01993                 client->ps.customRGBA[1] = 255;
01994         }
01995 
01996         value = Info_ValueForKey (userinfo, "char_color_blue");
01997         if (value)
01998         {
01999                 client->ps.customRGBA[2] = atoi(value);
02000         }
02001         else
02002         {
02003                 client->ps.customRGBA[2] = 255;
02004         }
02005 
02006         if ((client->ps.customRGBA[0]+client->ps.customRGBA[1]+client->ps.customRGBA[2]) < 100)
02007         { //hmm, too dark!
02008                 client->ps.customRGBA[0] = client->ps.customRGBA[1] = client->ps.customRGBA[2] = 255;
02009         }
02010 
02011         client->ps.customRGBA[3]=255;
02012 
02013         Q_strncpyz( forcePowers, Info_ValueForKey (userinfo, "forcepowers"), sizeof( forcePowers ) );
02014 
02015         // bots set their team a few frames later
02016         if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) {
02017                 s = Info_ValueForKey( userinfo, "team" );
02018                 if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
02019                         team = TEAM_RED;
02020                 } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
02021                         team = TEAM_BLUE;
02022                 } else {
02023                         // pick the team with the least number of players
02024                         team = PickTeam( clientNum );
02025                 }
02026         }
02027         else {
02028                 team = client->sess.sessionTeam;
02029         }
02030 
02031         //Set the siege class
02032         if (g_gametype.integer == GT_SIEGE)
02033         {
02034                 strcpy(className, client->sess.siegeClass);
02035 
02036                 //This function will see if the given class is legal for the given team.
02037                 //If not className will be filled in with the first legal class for this team.
02038 /*              if (!BG_SiegeCheckClassLegality(team, className) &&
02039                         Q_stricmp(client->sess.siegeClass, "none"))
02040                 { //if it isn't legal pop up the class menu
02041                         trap_SendServerCommand(ent-g_entities, "scl");
02042                 }
02043 */
02044                 //Now that the team is legal for sure, we'll go ahead and get an index for it.
02045                 client->siegeClass = BG_SiegeFindClassIndexByName(className);
02046                 if (client->siegeClass == -1)
02047                 { //ok, get the first valid class for the team you're on then, I guess.
02048                         BG_SiegeCheckClassLegality(team, className);
02049                         strcpy(client->sess.siegeClass, className);
02050                         client->siegeClass = BG_SiegeFindClassIndexByName(className);
02051                 }
02052                 else
02053                 { //otherwise, make sure the class we are using is legal.
02054                         G_ValidateSiegeClassForTeam(ent, team);
02055                         strcpy(className, client->sess.siegeClass);
02056                 }
02057 
02058                 //Set the sabers if the class dictates
02059                 if (client->siegeClass != -1)
02060                 {
02061                         siegeClass_t *scl = &bgSiegeClasses[client->siegeClass];
02062 
02063                         if (scl->saber1[0])
02064                         {
02065                                 G_SetSaber(ent, 0, scl->saber1, qtrue);
02066                         }
02067                         else
02068                         { //default I guess
02069                                 G_SetSaber(ent, 0, "Kyle", qtrue);
02070                         }
02071                         if (scl->saber2[0])
02072                         {
02073                                 G_SetSaber(ent, 1, scl->saber2, qtrue);
02074                         }
02075                         else
02076                         { //no second saber then
02077                                 G_SetSaber(ent, 1, "none", qtrue);
02078                         }
02079 
02080                         //make sure the saber models are updated
02081                         G_SaberModelSetup(ent);
02082 
02083                         if (scl->forcedModel[0])
02084                         { //be sure to override the model we actually use
02085                                 strcpy(model, scl->forcedModel);
02086                                 if (d_perPlayerGhoul2.integer)
02087                                 {
02088                                         if (Q_stricmp(model, client->modelname))
02089                                         {
02090                                                 strcpy(client->modelname, model);
02091                                                 modelChanged = qtrue;
02092                                         }
02093                                 }
02094                         }
02095 
02096                         //force them to use their class model on the server, if the class dictates
02097                         if (G_PlayerHasCustomSkeleton(ent))
02098                         {
02099                                 if (Q_stricmp(model, client->modelname) || ent->localAnimIndex == 0)
02100                                 {
02101                                         strcpy(client->modelname, model);
02102                                         modelChanged = qtrue;
02103                                 }
02104                         }
02105                 }
02106         }
02107         else
02108         {
02109                 strcpy(className, "none");
02110         }
02111 
02112         //Set the saber name
02113         strcpy(saberName, client->sess.saberType);
02114         strcpy(saber2Name, client->sess.saber2Type);
02115 
02116         // set max health
02117         if (g_gametype.integer == GT_SIEGE && client->siegeClass != -1)
02118         {
02119                 siegeClass_t *scl = &bgSiegeClasses[client->siegeClass];
02120                 maxHealth = 100;
02121 
02122                 if (scl->maxhealth)
02123                 {
02124                         maxHealth = scl->maxhealth;
02125                 }
02126 
02127                 health = maxHealth;
02128         }
02129         else
02130         {
02131                 maxHealth = 100;
02132                 health = 100; //atoi( Info_ValueForKey( userinfo, "handicap" ) );
02133         }
02134         client->pers.maxHealth = health;
02135         if ( client->pers.maxHealth < 1 || client->pers.maxHealth > maxHealth ) {
02136                 client->pers.maxHealth = 100;
02137         }
02138         client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
02139 
02140 /*      NOTE: all client side now
02141 
02142         // team
02143         switch( team ) {
02144         case TEAM_RED:
02145                 ForceClientSkin(client, model, "red");
02146 //              ForceClientSkin(client, headModel, "red");
02147                 break;
02148         case TEAM_BLUE:
02149                 ForceClientSkin(client, model, "blue");
02150 //              ForceClientSkin(client, headModel, "blue");
02151                 break;
02152         }
02153         // don't ever use a default skin in teamplay, it would just waste memory
02154         // however bots will always join a team but they spawn in as spectator
02155         if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) {
02156                 ForceClientSkin(client, model, "red");
02157 //              ForceClientSkin(client, headModel, "red");
02158         }
02159 */
02160 
02161         if (g_gametype.integer >= GT_TEAM) {
02162                 client->pers.teamInfo = qtrue;
02163         } else {
02164                 s = Info_ValueForKey( userinfo, "teamoverlay" );
02165                 if ( ! *s || atoi( s ) != 0 ) {
02166                         client->pers.teamInfo = qtrue;
02167                 } else {
02168                         client->pers.teamInfo = qfalse;
02169                 }
02170         }
02171         /*
02172         s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
02173         if ( !*s || atoi( s ) == 0 ) {
02174                 client->pers.pmoveFixed = qfalse;
02175         }
02176         else {
02177                 client->pers.pmoveFixed = qtrue;
02178         }
02179         */
02180 
02181         // team task (0 = none, 1 = offence, 2 = defence)
02182         teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
02183         // team Leader (1 = leader, 0 is normal player)
02184         teamLeader = client->sess.teamLeader;
02185 
02186         // colors
02187         strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
02188         strcpy(c2, Info_ValueForKey( userinfo, "color2" ));
02189 
02190 //      strcpy(redTeam, Info_ValueForKey( userinfo, "g_redteam" ));
02191 //      strcpy(blueTeam, Info_ValueForKey( userinfo, "g_blueteam" ));
02192 
02193         // send over a subset of the userinfo keys so other clients can
02194         // print scoreboards, display models, and play custom sounds
02195         if ( ent->r.svFlags & SVF_BOT ) {
02196                 s = va("n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d\\siegeclass\\%s\\st\\%s\\st2\\%s\\dt\\%i\\sdt\\%i",
02197                         client->pers.netname, team, model,  c1, c2, 
02198                         client->pers.maxHealth, client->sess.wins, client->sess.losses,
02199                         Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader, className, saberName, saber2Name, client->sess.duelTeam, client->sess.siegeDesiredTeam );
02200         } else {
02201                 if (g_gametype.integer == GT_SIEGE)
02202                 { //more crap to send
02203                         s = va("n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d\\siegeclass\\%s\\st\\%s\\st2\\%s\\dt\\%i\\sdt\\%i",
02204                                 client->pers.netname, client->sess.sessionTeam, model, c1, c2, 
02205                                 client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, teamLeader, className, saberName, saber2Name, client->sess.duelTeam, client->sess.siegeDesiredTeam);
02206                 }
02207                 else
02208                 {
02209                         s = va("n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d\\st\\%s\\st2\\%s\\dt\\%i",
02210                                 client->pers.netname, client->sess.sessionTeam, model, c1, c2, 
02211                                 client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, teamLeader, saberName, saber2Name, client->sess.duelTeam);
02212                 }
02213         }
02214 
02215         trap_SetConfigstring( CS_PLAYERS+clientNum, s );
02216 
02217         if (modelChanged) //only going to be true for allowable server-side custom skeleton cases
02218         { //update the server g2 instance if appropriate
02219                 char *modelname = Info_ValueForKey (userinfo, "model");
02220                 SetupGameGhoul2Model(ent, modelname, NULL);
02221 
02222                 if (ent->ghoul2 && ent->client)
02223                 {
02224                         ent->client->renderInfo.lastG2 = NULL; //update the renderinfo bolts next update.
02225                 }
02226 
02227                 client->torsoAnimExecute = client->legsAnimExecute = -1;
02228                 client->torsoLastFlip = client->legsLastFlip = qfalse;
02229         }
02230 
02231         if (g_logClientInfo.integer)
02232         {
02233                 G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
02234         }
02235 }

void G_BreakArm gentity_t ent,
int  arm
 

Definition at line 2608 of file g_client.c.

References BOTH_PAIN2, BOTH_PAIN3, BROKENLIMB_LARM, BROKENLIMB_RARM, playerState_s::brokenLimbs, CHAN_AUTO, CHAN_VOICE, CLASS_VEHICLE, gentity_s::client, clientPersistant_t::cmd, playerState_s::fd, G_EntitySound(), G_SetAnim(), G_Sound(), G_SoundIndex(), gentity_t, gentity_s::localAnimIndex, saberInfo_t::model, entityState_s::NPC_class, gclient_s::pers, gclient_s::ps, Q_irand(), gentity_s::s, gclient_s::saber, forcedata_s::saberAnimLevel, playerState_s::saberHolstered, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, saberInfo_t::soundOff, SS_STAFF, va(), playerState_s::weapon, and WP_SABER.

Referenced by ClientCommand(), G_Damage(), and player_die().

02609 {
02610         int anim = -1;
02611 
02612         assert(ent && ent->client);
02613 
02614         if (ent->s.NPC_class == CLASS_VEHICLE || ent->localAnimIndex > 1)
02615         { //no broken limbs for vehicles and non-humanoids
02616                 return;
02617         }
02618 
02619         if (!arm)
02620         { //repair him
02621                 ent->client->ps.brokenLimbs = 0;
02622                 return;
02623         }
02624 
02625         if (ent->client->ps.fd.saberAnimLevel == SS_STAFF)
02626         { //I'm too lazy to deal with this as well for now.
02627                 return;
02628         }
02629 
02630         if (arm == BROKENLIMB_LARM)
02631         {
02632                 if (ent->client->saber[1].model[0] &&
02633                         ent->client->ps.weapon == WP_SABER &&
02634                         !ent->client->ps.saberHolstered &&
02635                         ent->client->saber[1].soundOff)
02636                 { //the left arm shuts off its saber upon being broken
02637                         G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02638                 }
02639         }
02640 
02641         ent->client->ps.brokenLimbs = 0; //make sure it's cleared out
02642         ent->client->ps.brokenLimbs |= (1 << arm); //this arm is now marked as broken
02643 
02644         //Do a pain anim based on the side. Since getting your arm broken does tend to hurt.
02645         if (arm == BROKENLIMB_LARM)
02646         {
02647                 anim = BOTH_PAIN2;
02648         }
02649         else if (arm == BROKENLIMB_RARM)
02650         {
02651                 anim = BOTH_PAIN3;
02652         }
02653 
02654         if (anim == -1)
02655         {
02656                 return;
02657         }
02658 
02659         G_SetAnim(ent, &ent->client->pers.cmd, SETANIM_BOTH, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
02660 
02661         //This could be combined into a single event. But I guess limbs don't break often enough to
02662         //worry about it.
02663         G_EntitySound( ent, CHAN_VOICE, G_SoundIndex("*pain25.wav") );
02664         //FIXME: A nice bone snapping sound instead if possible
02665         G_Sound(ent, CHAN_AUTO, G_SoundIndex( va("sound/player/bodyfall_human%i.wav", Q_irand(1, 3)) ));
02666 }

qboolean G_SaberModelSetup gentity_t ent  ) 
 

Definition at line 1423 of file g_client.c.

References gentity_s::client, gentity_t, gentity_s::ghoul2, MAX_SABERS, saberInfo_t::model, saberInfo_t::numBlades, qboolean, qfalse, qtrue, gclient_s::saber, saberInfo_t::saberFlags, SFL_BOLT_TO_WRIST, saberInfo_t::skin, trap_G2API_AddBolt(), trap_G2API_CleanGhoul2Models(), trap_G2API_CopySpecificGhoul2Model(), trap_G2API_InitGhoul2Model(), trap_G2API_SetBoltInfo(), trap_G2API_SetSkin(), va(), and gclient_s::weaponGhoul2.

Referenced by ClientSpawn(), ClientUserinfoChanged(), and SetupGameGhoul2Model().

01424 {
01425         int i = 0;
01426         qboolean fallbackForSaber = qtrue;
01427 
01428         while (i < MAX_SABERS)
01429         {
01430                 if (ent->client->saber[i].model[0])
01431                 {
01432                         //first kill it off if we've already got it
01433                         if (ent->client->weaponGhoul2[i])
01434                         {
01435                                 trap_G2API_CleanGhoul2Models(&(ent->client->weaponGhoul2[i]));
01436                         }
01437                         trap_G2API_InitGhoul2Model(&ent->client->weaponGhoul2[i], ent->client->saber[i].model, 0, 0, -20, 0, 0);
01438 
01439                         if (ent->client->weaponGhoul2[i])
01440                         {
01441                                 int j = 0;
01442                                 char *tagName;
01443                                 int tagBolt;
01444 
01445                                 if (ent->client->saber[i].skin)
01446                                 {
01447                                         trap_G2API_SetSkin(ent->client->weaponGhoul2[i], 0, ent->client->saber[i].skin, ent->client->saber[i].skin);
01448                                 }
01449 
01450                                 if (ent->client->saber[i].saberFlags & SFL_BOLT_TO_WRIST)
01451                                 {
01452                                         trap_G2API_SetBoltInfo(ent->client->weaponGhoul2[i], 0, 3+i);
01453                                 }
01454                                 else
01455                                 { // bolt to right hand for 0, or left hand for 1
01456                                         trap_G2API_SetBoltInfo(ent->client->weaponGhoul2[i], 0, i);
01457                                 }
01458 
01459                                 //Add all the bolt points
01460                                 while (j < ent->client->saber[i].numBlades)
01461                                 {
01462                                         tagName = va("*blade%i", j+1);
01463                                         tagBolt = trap_G2API_AddBolt(ent->client->weaponGhoul2[i], 0, tagName);
01464 
01465                                         if (tagBolt == -1)
01466                                         {
01467                                                 if (j == 0)
01468                                                 { //guess this is an 0ldsk3wl saber
01469                                                         tagBolt = trap_G2API_AddBolt(ent->client->weaponGhoul2[i], 0, "*flash");
01470                                                         fallbackForSaber = qfalse;
01471                                                         break;
01472                                                 }
01473 
01474                                                 if (tagBolt == -1)
01475                                                 {
01476                                                         assert(0);
01477                                                         break;
01478 
01479                                                 }
01480                                         }
01481                                         j++;
01482 
01483                                         fallbackForSaber = qfalse; //got at least one custom saber so don't need default
01484                                 }
01485 
01486                                 //Copy it into the main instance
01487                                 trap_G2API_CopySpecificGhoul2Model(ent->client->weaponGhoul2[i], 0, ent->ghoul2, i+1); 
01488                         }
01489                 }
01490                 else
01491                 {
01492                         break;
01493                 }
01494 
01495                 i++;
01496         }
01497 
01498         return fallbackForSaber;
01499 }

qboolean G_SetSaber gentity_t ent,
int  saberNum,
char *  saberName,
qboolean  siegeOverride
 

Definition at line 1305 of file g_cmds.c.

References bgSiegeClasses, gentity_s::client, playerState_s::fd, g_gametype, gentity_t, GT_SIEGE, vmCvar_t::integer, saberInfo_t::model, saberInfo_t::name, entityState_s::number, gclient_s::ps, Q_stricmp(), qboolean, qfalse, qtrue, gentity_s::s, gclient_s::saber, clientSession_t::saber2Type, forcedata_s::saberAnimLevel, forcedata_s::saberAnimLevelBase, gclient_s::saberCycleQueue, playerState_s::saberHolstered, clientSession_t::saberType, gclient_s::sess, gclient_s::siegeClass, strcpy(), WP_SaberStyleValidForSaber(), WP_SetSaber(), and WP_UseFirstValidSaberStyle().

Referenced by ClientBegin(), ClientSpawn(), and ClientUserinfoChanged().

01306 {
01307         char truncSaberName[64];
01308         int i = 0;
01309 
01310         if (!siegeOverride &&
01311                 g_gametype.integer == GT_SIEGE &&
01312                 ent->client->siegeClass != -1 &&
01313                 (
01314                  bgSiegeClasses[ent->client->siegeClass].saberStance ||
01315                  bgSiegeClasses[ent->client->siegeClass].saber1[0] ||
01316                  bgSiegeClasses[ent->client->siegeClass].saber2[0]
01317                 ))
01318         { //don't let it be changed if the siege class has forced any saber-related things
01319         return qfalse;
01320         }
01321 
01322         while (saberName[i] && i < 64-1)
01323         {
01324         truncSaberName[i] = saberName[i];
01325                 i++;
01326         }
01327         truncSaberName[i] = 0;
01328 
01329         if ( saberNum == 0 && (Q_stricmp( "none", truncSaberName ) == 0 || Q_stricmp( "remove", truncSaberName ) == 0) )
01330         { //can't remove saber 0 like this
01331         strcpy(truncSaberName, "Kyle");
01332         }
01333 
01334         //Set the saber with the arg given. If the arg is
01335         //not a valid sabername defaults will be used.
01336         WP_SetSaber(ent->s.number, ent->client->saber, saberNum, truncSaberName);
01337 
01338         if (!ent->client->saber[0].model[0])
01339         {
01340                 assert(0); //should never happen!
01341                 strcpy(ent->client->sess.saberType, "none");
01342         }
01343         else
01344         {
01345                 strcpy(ent->client->sess.saberType, ent->client->saber[0].name);
01346         }
01347 
01348         if (!ent->client->saber[1].model[0])
01349         {
01350                 strcpy(ent->client->sess.saber2Type, "none");
01351         }
01352         else
01353         {
01354                 strcpy(ent->client->sess.saber2Type, ent->client->saber[1].name);
01355         }
01356 
01357         if ( !WP_SaberStyleValidForSaber( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, ent->client->ps.fd.saberAnimLevel ) )
01358         {
01359                 WP_UseFirstValidSaberStyle( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, &ent->client->ps.fd.saberAnimLevel );
01360                 ent->client->ps.fd.saberAnimLevelBase = ent->client->saberCycleQueue = ent->client->ps.fd.saberAnimLevel;
01361         }
01362 
01363         return qtrue;
01364 }

void G_UpdateClientAnims gentity_t self,
float  animSpeedScale
 

Definition at line 2673 of file g_client.c.

References animation_t, BG_SaberStanceAnim(), BG_SaberStartTransAnim(), bgAllAnims, BONE_ANIM_BLEND, BONE_ANIM_OVERRIDE_FREEZE, BONE_ANIM_OVERRIDE_LOOP, BOTH_ATTACK2, BOTH_DEAD21, BOTH_MELEE1, BOTH_MELEE2, BOTH_STAND2, BROKENLIMB_LARM, BROKENLIMB_RARM, playerState_s::brokenLimbs, gclient_s::brokenLimbs, CLASS_VEHICLE, gentity_s::client, playerState_s::fd, animation_s::firstFrame, animation_s::frameLerp, gentity_t, gentity_s::ghoul2, playerState_s::legsAnim, gclient_s::legsAnimExecute, playerState_s::legsFlip, gclient_s::legsLastFlip, level, gentity_s::localAnimIndex, MAX_CLIENTS, saberInfo_t::model, gentity_s::noLumbar, entityState_s::NPC_class, NULL, entityState_s::number, animation_s::numFrames, PM_RunningAnim(), gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::s, gclient_s::saber, forcedata_s::saberAnimLevel, playerState_s::saberLockFrame, level_locals_t::time, TORSO_WEAPONREADY2, playerState_s::torsoAnim, gclient_s::torsoAnimExecute, playerState_s::torsoFlip, gclient_s::torsoLastFlip, trap_G2API_RemoveBone(), trap_G2API_SetBoneAnim(), playerState_s::weapon, WP_BRYAR_PISTOL, WP_MELEE, and WP_SABER.

Referenced by player_die(), and WP_SaberPositionUpdate().

02674 {
02675         static int f;
02676         static int torsoAnim;
02677         static int legsAnim;
02678         static int firstFrame, lastFrame;
02679         static int aFlags;
02680         static float animSpeed, lAnimSpeedScale;
02681         qboolean setTorso = qfalse;
02682 
02683         torsoAnim = (self->client->ps.torsoAnim);
02684         legsAnim = (self->client->ps.legsAnim);
02685 
02686         if (self->client->ps.saberLockFrame)
02687         {
02688                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "model_root", self->client->ps.saberLockFrame, self->client->ps.saberLockFrame+1, BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, animSpeedScale, level.time, -1, 150);
02689                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "lower_lumbar", self->client->ps.saberLockFrame, self->client->ps.saberLockFrame+1, BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, animSpeedScale, level.time, -1, 150);
02690                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "Motion", self->client->ps.saberLockFrame, self->client->ps.saberLockFrame+1, BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, animSpeedScale, level.time, -1, 150);
02691                 return;
02692         }
02693 
02694         if (self->localAnimIndex > 1 &&
02695                 bgAllAnims[self->localAnimIndex].anims[legsAnim].firstFrame == 0 &&
02696                 bgAllAnims[self->localAnimIndex].anims[legsAnim].numFrames == 0)
02697         { //We'll allow this for non-humanoids.
02698                 goto tryTorso;
02699         }
02700 
02701         if (self->client->legsAnimExecute != legsAnim || self->client->legsLastFlip != self->client->ps.legsFlip)
02702         {
02703                 animSpeed = 50.0f / bgAllAnims[self->localAnimIndex].anims[legsAnim].frameLerp;
02704                 lAnimSpeedScale = (animSpeed *= animSpeedScale);
02705 
02706                 if (bgAllAnims[self->localAnimIndex].anims[legsAnim].loopFrames != -1)
02707                 {
02708                         aFlags = BONE_ANIM_OVERRIDE_LOOP;
02709                 }
02710                 else
02711                 {
02712                         aFlags = BONE_ANIM_OVERRIDE_FREEZE;
02713                 }
02714 
02715                 if (animSpeed < 0)
02716                 {
02717                         lastFrame = bgAllAnims[self->localAnimIndex].anims[legsAnim].firstFrame;
02718                         firstFrame = bgAllAnims[self->localAnimIndex].anims[legsAnim].firstFrame + bgAllAnims[self->localAnimIndex].anims[legsAnim].numFrames;
02719                 }
02720                 else
02721                 {
02722                         firstFrame = bgAllAnims[self->localAnimIndex].anims[legsAnim].firstFrame;
02723                         lastFrame = bgAllAnims[self->localAnimIndex].anims[legsAnim].firstFrame + bgAllAnims[self->localAnimIndex].anims[legsAnim].numFrames;
02724                 }
02725 
02726                 aFlags |= BONE_ANIM_BLEND; //since client defaults to blend. Not sure if this will make much difference if any on server position, but it's here just for the sake of matching them.
02727 
02728                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "model_root", firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02729                 self->client->legsAnimExecute = legsAnim;
02730                 self->client->legsLastFlip = self->client->ps.legsFlip;
02731         }
02732 
02733 tryTorso:
02734         if (self->localAnimIndex > 1 &&
02735                 bgAllAnims[self->localAnimIndex].anims[torsoAnim].firstFrame == 0 &&
02736                 bgAllAnims[self->localAnimIndex].anims[torsoAnim].numFrames == 0)
02737 
02738         { //If this fails as well just return.
02739                 return;
02740         }
02741         else if (self->s.number >= MAX_CLIENTS &&
02742                 self->s.NPC_class == CLASS_VEHICLE)
02743         { //we only want to set the root bone for vehicles
02744                 return;
02745         }
02746 
02747         if ((self->client->torsoAnimExecute != torsoAnim || self->client->torsoLastFlip != self->client->ps.torsoFlip) &&
02748                 !self->noLumbar)
02749         {
02750                 aFlags = 0;
02751                 animSpeed = 0;
02752 
02753                 f = torsoAnim;
02754 
02755                 BG_SaberStartTransAnim(self->s.number, self->client->ps.fd.saberAnimLevel, self->client->ps.weapon, f, &animSpeedScale, self->client->ps.brokenLimbs);
02756 
02757                 animSpeed = 50.0f / bgAllAnims[self->localAnimIndex].anims[f].frameLerp;
02758                 lAnimSpeedScale = (animSpeed *= animSpeedScale);
02759 
02760                 if (bgAllAnims[self->localAnimIndex].anims[f].loopFrames != -1)
02761                 {
02762                         aFlags = BONE_ANIM_OVERRIDE_LOOP;
02763                 }
02764                 else
02765                 {
02766                         aFlags = BONE_ANIM_OVERRIDE_FREEZE;
02767                 }
02768 
02769                 aFlags |= BONE_ANIM_BLEND; //since client defaults to blend. Not sure if this will make much difference if any on client position, but it's here just for the sake of matching them.
02770 
02771                 if (animSpeed < 0)
02772                 {
02773                         lastFrame = bgAllAnims[self->localAnimIndex].anims[f].firstFrame;
02774                         firstFrame = bgAllAnims[self->localAnimIndex].anims[f].firstFrame + bgAllAnims[self->localAnimIndex].anims[f].numFrames;
02775                 }
02776                 else
02777                 {
02778                         firstFrame = bgAllAnims[self->localAnimIndex].anims[f].firstFrame;
02779                         lastFrame = bgAllAnims[self->localAnimIndex].anims[f].firstFrame + bgAllAnims[self->localAnimIndex].anims[f].numFrames;
02780                 }
02781 
02782                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "lower_lumbar", firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, /*firstFrame why was it this before?*/-1, 150);
02783 
02784                 self->client->torsoAnimExecute = torsoAnim;
02785                 self->client->torsoLastFlip = self->client->ps.torsoFlip;
02786                 
02787                 setTorso = qtrue;
02788         }
02789 
02790         if (setTorso &&
02791                 self->localAnimIndex <= 1)
02792         { //only set the motion bone for humanoids.
02793                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "Motion", firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02794         }
02795 
02796 #if 0 //disabled for now
02797         if (self->client->ps.brokenLimbs != self->client->brokenLimbs ||
02798                 setTorso)
02799         {
02800                 if (self->localAnimIndex <= 1 && self->client->ps.brokenLimbs &&
02801                         (self->client->ps.brokenLimbs & (1 << BROKENLIMB_LARM)))
02802                 { //broken left arm
02803                         char *brokenBone = "lhumerus";
02804                         animation_t *armAnim;
02805                         int armFirstFrame;
02806                         int armLastFrame;
02807                         int armFlags = 0;
02808                         float armAnimSpeed;
02809 
02810                         armAnim = &bgAllAnims[self->localAnimIndex].anims[ BOTH_DEAD21 ];
02811                         self->client->brokenLimbs = self->client->ps.brokenLimbs;
02812 
02813                         armFirstFrame = armAnim->firstFrame;
02814                         armLastFrame = armAnim->firstFrame+armAnim->numFrames;
02815                         armAnimSpeed = 50.0f / armAnim->frameLerp;
02816                         armFlags = (BONE_ANIM_OVERRIDE_LOOP|BONE_ANIM_BLEND);
02817 
02818                         trap_G2API_SetBoneAnim(self->ghoul2, 0, brokenBone, armFirstFrame, armLastFrame, armFlags, armAnimSpeed, level.time, -1, 150);
02819                 }
02820                 else if (self->localAnimIndex <= 1 && self->client->ps.brokenLimbs &&
02821                         (self->client->ps.brokenLimbs & (1 << BROKENLIMB_RARM)))
02822                 { //broken right arm
02823                         char *brokenBone = "rhumerus";
02824                         char *supportBone = "lhumerus";
02825 
02826                         self->client->brokenLimbs = self->client->ps.brokenLimbs;
02827 
02828                         //Only put the arm in a broken pose if the anim is such that we
02829                         //want to allow it.
02830                         if ((//self->client->ps.weapon == WP_MELEE ||
02831                                 self->client->ps.weapon != WP_SABER ||
02832                                 BG_SaberStanceAnim(self->client->ps.torsoAnim) ||
02833                                 PM_RunningAnim(self->client->ps.torsoAnim)) &&
02834                                 (!self->client->saber[1].model[0] || self->client->ps.weapon != WP_SABER))
02835                         {
02836                                 int armFirstFrame;
02837                                 int armLastFrame;
02838                                 int armFlags = 0;
02839                                 float armAnimSpeed;
02840                                 animation_t *armAnim;
02841 
02842                                 if (self->client->ps.weapon == WP_MELEE ||
02843                                         self->client->ps.weapon == WP_SABER ||
02844                                         self->client->ps.weapon == WP_BRYAR_PISTOL)
02845                                 { //don't affect this arm if holding a gun, just make the other arm support it
02846                                         armAnim = &bgAllAnims[self->localAnimIndex].anims[ BOTH_ATTACK2 ];
02847 
02848                                         //armFirstFrame = armAnim->firstFrame;
02849                                         armFirstFrame = armAnim->firstFrame+armAnim->numFrames;
02850                                         armLastFrame = armAnim->firstFrame+armAnim->numFrames;
02851                                         armAnimSpeed = 50.0f / armAnim->frameLerp;
02852                                         armFlags = (BONE_ANIM_OVERRIDE_LOOP|BONE_ANIM_BLEND);
02853 
02854                                         trap_G2API_SetBoneAnim(self->ghoul2, 0, brokenBone, armFirstFrame, armLastFrame, armFlags, armAnimSpeed, level.time, -1, 150);
02855                                 }
02856                                 else
02857                                 { //we want to keep the broken bone updated for some cases
02858                                         trap_G2API_SetBoneAnim(self->ghoul2, 0, brokenBone, firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02859                                 }
02860 
02861                                 if (self->client->ps.torsoAnim != BOTH_MELEE1 &&
02862                                         self->client->ps.torsoAnim != BOTH_MELEE2 &&
02863                                         (self->client->ps.torsoAnim == TORSO_WEAPONREADY2 || self->client->ps.torsoAnim == BOTH_ATTACK2 || self->client->ps.weapon < WP_BRYAR_PISTOL))
02864                                 {
02865                                         //Now set the left arm to "support" the right one
02866                                         armAnim = &bgAllAnims[self->localAnimIndex].anims[ BOTH_STAND2 ];
02867                                         armFirstFrame = armAnim->firstFrame;
02868                                         armLastFrame = armAnim->firstFrame+armAnim->numFrames;
02869                                         armAnimSpeed = 50.0f / armAnim->frameLerp;
02870                                         armFlags = (BONE_ANIM_OVERRIDE_LOOP|BONE_ANIM_BLEND);
02871 
02872                                         trap_G2API_SetBoneAnim(self->ghoul2, 0, supportBone, armFirstFrame, armLastFrame, armFlags, armAnimSpeed, level.time, -1, 150);
02873                                 }
02874                                 else
02875                                 { //we want to keep the support bone updated for some cases
02876                                         trap_G2API_SetBoneAnim(self->ghoul2, 0, supportBone, firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02877                                 }
02878                         }
02879                         else
02880                         { //otherwise, keep it set to the same as the torso
02881                                 trap_G2API_SetBoneAnim(self->ghoul2, 0, brokenBone, firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02882                                 trap_G2API_SetBoneAnim(self->ghoul2, 0, supportBone, firstFrame, lastFrame, aFlags, lAnimSpeedScale, level.time, -1, 150);
02883                         }
02884                 }
02885                 else if (self->client->brokenLimbs)
02886                 { //remove the bone now so it can be set again
02887                         char *brokenBone = NULL;
02888                         int broken = 0;
02889 
02890                         //Warning: Don't remove bones that you've added as bolts unless you want to invalidate your bolt index
02891                         //(well, in theory, I haven't actually run into the problem)
02892                         if (self->client->brokenLimbs & (1<<BROKENLIMB_LARM))
02893                         {
02894                                 brokenBone = "lhumerus";
02895                                 broken |= (1<<BROKENLIMB_LARM);
02896                         }
02897                         else if (self->client->brokenLimbs & (1<<BROKENLIMB_RARM))
02898                         { //can only have one arm broken at once.
02899                                 brokenBone = "rhumerus";
02900                                 broken |= (1<<BROKENLIMB_RARM);
02901 
02902                                 //want to remove the support bone too then
02903                                 trap_G2API_SetBoneAnim(self->ghoul2, 0, "lhumerus", 0, 1, 0, 0, level.time, -1, 0);
02904                                 trap_G2API_RemoveBone(self->ghoul2, "lhumerus", 0);
02905                         }
02906 
02907                         assert(brokenBone);
02908 
02909                         //Set the flags and stuff to 0, so that the remove will succeed
02910                         trap_G2API_SetBoneAnim(self->ghoul2, 0, brokenBone, 0, 1, 0, 0, level.time, -1, 0);
02911 
02912                         //Now remove it
02913                         trap_G2API_RemoveBone(self->ghoul2, brokenBone, 0);
02914                         self->client->brokenLimbs &= ~broken;
02915                 }
02916         }
02917 #endif
02918 }

void G_ValidateSiegeClassForTeam gentity_t ent,
int  team
 

Definition at line 744 of file g_saga.c.

References BG_SiegeFindClassIndexByName(), BG_SiegeFindThemeForTeam(), bgSiegeClasses, siegeTeam_t::classes, gentity_s::client, gentity_t, siegeClass_t::name, siegeTeam_t::numClasses, siegeClass_t::playerClass, Q_stricmp(), gclient_s::sess, gclient_s::siegeClass, clientSession_t::siegeClass, and strcpy().

Referenced by ClientUserinfoChanged(), and SetTeamQuick().

00745 {
00746         siegeClass_t *scl;
00747         siegeTeam_t *stm;
00748         int newClassIndex = -1;
00749         if (ent->client->siegeClass == -1)
00750         { //uh.. sure.
00751                 return;
00752         }
00753 
00754         scl = &bgSiegeClasses[ent->client->siegeClass];
00755 
00756         stm = BG_SiegeFindThemeForTeam(team);
00757         if (stm)
00758         {
00759                 int i = 0;
00760 
00761                 while (i < stm->numClasses)
00762                 { //go through the team and see its valid classes, can we find one that matches our current player class?
00763                         if (stm->classes[i])
00764                         {
00765                                 if (!Q_stricmp(scl->name, stm->classes[i]->name))
00766                                 { //the class we're using is already ok for this team.
00767                                         return;
00768                                 }
00769                                 if (stm->classes[i]->playerClass == scl->playerClass ||
00770                                         newClassIndex == -1)
00771                                 {
00772                                         newClassIndex = i;
00773                                 }
00774                         }
00775                         i++;
00776                 }
00777 
00778                 if (newClassIndex != -1)
00779                 { //ok, let's find it in the global class array
00780                         ent->client->siegeClass = BG_SiegeFindClassIndexByName(stm->classes[newClassIndex]->name);
00781                         strcpy(ent->client->sess.siegeClass, stm->classes[newClassIndex]->name);
00782                 }
00783         }
00784 }

void G_WriteClientSessionData gclient_t client  ) 
 

Definition at line 23 of file g_session.c.

References client, level_locals_t::clients, clientSession_t::duelTeam, gclient_t, level, clientSession_t::losses, clientSession_t::saber2Type, clientSession_t::saberLevel, clientSession_t::saberType, clientSession_t::selectedFP, gclient_s::sess, clientSession_t::sessionTeam, clientSession_t::setForce, clientSession_t::siegeClass, clientSession_t::siegeDesiredTeam, clientSession_t::spectatorClient, clientSession_t::spectatorState, clientSession_t::spectatorTime, strcpy(), clientSession_t::teamLeader, trap_Cvar_Set(), va(), and clientSession_t::wins.

Referenced by ClientBegin(), G_InitSessionData(), and G_WriteSessionData().

00023                                                    {
00024         const char      *s;
00025         const char      *var;
00026         int                     i = 0;
00027         char            siegeClass[64];
00028         char            saberType[64];
00029         char            saber2Type[64];
00030 
00031         strcpy(siegeClass, client->sess.siegeClass);
00032 
00033         while (siegeClass[i])
00034         { //sort of a hack.. we don't want spaces by siege class names have spaces so convert them all to unused chars
00035                 if (siegeClass[i] == ' ')
00036                 {
00037                         siegeClass[i] = 1;
00038                 }
00039 
00040                 i++;
00041         }
00042 
00043         if (!siegeClass[0])
00044         { //make sure there's at least something
00045                 strcpy(siegeClass, "none");
00046         }
00047 
00048         //Do the same for the saber
00049         strcpy(saberType, client->sess.saberType);
00050 
00051         i = 0;
00052         while (saberType[i])
00053         {
00054                 if (saberType[i] == ' ')
00055                 {
00056                         saberType[i] = 1;
00057                 }
00058 
00059                 i++;
00060         }
00061 
00062         strcpy(saber2Type, client->sess.saber2Type);
00063 
00064         i = 0;
00065         while (saber2Type[i])
00066         {
00067                 if (saber2Type[i] == ' ')
00068                 {
00069                         saber2Type[i] = 1;
00070                 }
00071 
00072                 i++;
00073         }
00074 
00075         s = va("%i %i %i %i %i %i %i %i %i %i %i %i %s %s %s", 
00076                 client->sess.sessionTeam,
00077                 client->sess.spectatorTime,
00078                 client->sess.spectatorState,
00079                 client->sess.spectatorClient,
00080                 client->sess.wins,
00081                 client->sess.losses,
00082                 client->sess.teamLeader,
00083                 client->sess.setForce,
00084                 client->sess.saberLevel,
00085                 client->sess.selectedFP,
00086                 client->sess.duelTeam,
00087                 client->sess.siegeDesiredTeam,
00088                 siegeClass,
00089                 saberType,
00090                 saber2Type
00091                 );
00092 
00093         var = va( "session%i", client - level.clients );
00094 
00095         trap_Cvar_Set( var, s );
00096 }

void InitBodyQue void   ) 
 

Definition at line 953 of file g_client.c.

References BODY_QUEUE_SIZE, level_locals_t::bodyQue, level_locals_t::bodyQueIndex, gentity_s::classname, G_Spawn(), gentity_t, level, gentity_s::neverFree, and qtrue.

Referenced by G_InitGame().

00953                         {
00954         int             i;
00955         gentity_t       *ent;
00956 
00957         level.bodyQueIndex = 0;
00958         for (i=0; i<BODY_QUEUE_SIZE ; i++) {
00959                 ent = G_Spawn();
00960                 ent->classname = "bodyque";
00961                 ent->neverFree = qtrue;
00962                 level.bodyQue[i] = ent;
00963         }
00964 }

void JMSaberThink gentity_t ent  ) 
 

Definition at line 346 of file g_client.c.

References EF_NODRAW, ET_MISSILE, G_ModelIndex(), G_RunObject(), gentity_t, gJMSaberEnt, JMSABER_RESPAWN_TIME, level, NULL, level_locals_t::time, trap_LinkEntity(), and VectorCopy.

Referenced by SP_info_jedimaster_start().

00347 {
00348         gJMSaberEnt = ent;
00349 
00350         if (ent->enemy)
00351         {
00352                 if (!ent->enemy->client || !ent->enemy->inuse)
00353                 { //disconnected?
00354                         VectorCopy(ent->enemy->s.pos.trBase, ent->s.pos.trBase);
00355                         VectorCopy(ent->enemy->s.pos.trBase, ent->s.origin);
00356                         VectorCopy(ent->enemy->s.pos.trBase, ent->r.currentOrigin);
00357                         ent->s.modelindex = G_ModelIndex("models/weapons2/saber/saber_w.glm");
00358                         ent->s.eFlags &= ~(EF_NODRAW);
00359                         ent->s.modelGhoul2 = 1;
00360                         ent->s.eType = ET_MISSILE;
00361                         ent->enemy = NULL;
00362 
00363                         ent->pos2[0] = 1;
00364                         ent->pos2[1] = 0; //respawn next think
00365                         trap_LinkEntity(ent);
00366                 }
00367                 else
00368                 {
00369                         ent->pos2[1] = level.time + JMSABER_RESPAWN_TIME;
00370                 }
00371         }
00372         else if (ent->pos2[0] && ent->pos2[1] < level.time)
00373         {
00374                 VectorCopy(ent->s.origin2, ent->s.pos.trBase);
00375                 VectorCopy(ent->s.origin2, ent->s.origin);
00376                 VectorCopy(ent->s.origin2, ent->r.currentOrigin);
00377                 ent->pos2[0] = 0;
00378                 trap_LinkEntity(ent);
00379         }
00380 
00381         ent->nextthink = level.time + 50;
00382         G_RunObject(ent);
00383 }

void JMSaberTouch gentity_t self,
gentity_t other,
trace_t trace
 

Definition at line 385 of file g_client.c.

References gentity_s::client, CS_CLIENT_JEDIMASTER, EF_INVULNERABLE, EF_NODRAW, entityState_s::eFlags, playerState_s::eFlags, gentity_s::enemy, ET_GENERAL, entityState_s::eType, EV_BECOME_JEDIMASTER, playerState_s::fd, FORCE_LEVEL_3, forcedata_s::forcePower, forcedata_s::forcePowerLevel, forcedata_s::forcePowersKnown, G_AddEvent(), G_GetStringEdString(), G_KillG2Queue(), g_spawnInvulnerability, gentity_t, gentity_s::health, vmCvar_t::integer, gclient_s::invulnerableTimer, playerState_s::isJediMaster, JMSABER_RESPAWN_TIME, level, entityState_s::modelGhoul2, entityState_s::modelindex, clientPersistant_t::netname, NUM_FORCE_POWERS, entityState_s::number, gclient_s::pers, gentity_s::pos2, gclient_s::ps, qtrue, gentity_s::s, playerState_s::saberIndex, STAT_HEALTH, STAT_WEAPONS, playerState_s::stats, level_locals_t::time, trap_SendServerCommand(), trap_SetConfigstring(), va(), entityState_s::weapon, playerState_s::weapon, and WP_SABER.

Referenced by SP_info_jedimaster_start().

00386 {
00387         int i = 0;
00388 //      gentity_t *te;
00389 
00390         if (!other || !other->client || other->health < 1)
00391         {
00392                 return;
00393         }
00394 
00395         if (self->enemy)
00396         {
00397                 return;
00398         }
00399 
00400         if (!self->s.modelindex)
00401         {
00402                 return;
00403         }
00404 
00405         if (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_SABER))
00406         {
00407                 return;
00408         }
00409 
00410         if (other->client->ps.isJediMaster)
00411         {
00412                 return;
00413         }
00414 
00415         self->enemy = other;
00416         other->client->ps.stats[STAT_WEAPONS] = (1 << WP_SABER);
00417         other->client->ps.weapon = WP_SABER;
00418         other->s.weapon = WP_SABER;
00419         G_AddEvent(other, EV_BECOME_JEDIMASTER, 0);
00420 
00421         // Track the jedi master 
00422         trap_SetConfigstring ( CS_CLIENT_JEDIMASTER, va("%i", other->s.number ) );
00423 
00424         if (g_spawnInvulnerability.integer)
00425         {
00426                 other->client->ps.eFlags |= EF_INVULNERABLE;
00427                 other->client->invulnerableTimer = level.time + g_spawnInvulnerability.integer;
00428         }
00429 
00430         trap_SendServerCommand( -1, va("cp \"%s %s\n\"", other->client->pers.netname, G_GetStringEdString("MP_SVGAME", "BECOMEJM")) );
00431 
00432         other->client->ps.isJediMaster = qtrue;
00433         other->client->ps.saberIndex = self->s.number;
00434 
00435         if (other->health < 200 && other->health > 0)
00436         { //full health when you become the Jedi Master
00437                 other->client->ps.stats[STAT_HEALTH] = other->health = 200;
00438         }
00439 
00440         if (other->client->ps.fd.forcePower < 100)
00441         {
00442                 other->client->ps.fd.forcePower = 100;
00443         }
00444 
00445         while (i < NUM_FORCE_POWERS)
00446         {
00447                 other->client->ps.fd.forcePowersKnown |= (1 << i);
00448                 other->client->ps.fd.forcePowerLevel[i] = FORCE_LEVEL_3;
00449 
00450                 i++;
00451         }
00452 
00453         self->pos2[0] = 1;
00454         self->pos2[1] = level.time + JMSABER_RESPAWN_TIME;
00455 
00456         self->s.modelindex = 0;
00457         self->s.eFlags |= EF_NODRAW;
00458         self->s.modelGhoul2 = 0;
00459         self->s.eType = ET_GENERAL;
00460 
00461         /*
00462         te = G_TempEntity( vec3_origin, EV_DESTROY_GHOUL2_INSTANCE );
00463         te->r.svFlags |= SVF_BROADCAST;
00464         te->s.eventParm = self->s.number;
00465         */
00466         G_KillG2Queue(self->s.number);
00467 
00468         return;
00469 }

void MaintainBodyQueue gentity_t ent  ) 
 

Definition at line 1130 of file g_client.c.

References gentity_s::client, entityState_s::clientNum, EF2_SHIP_DEATH, playerState_s::eFlags2, playerState_s::fallingToDeath, gentity_t, level, gclient_s::noCorpse, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::s, gclient_s::tempSpectate, level_locals_t::time, trap_SendServerCommand(), and va().

Referenced by respawn(), and SetTeam().

01131 { //do whatever should be done taking ragdoll and dismemberment states into account.
01132         qboolean doRCG = qfalse;
01133 
01134         assert(ent && ent->client);
01135         if (ent->client->tempSpectate > level.time ||
01136                 (ent->client->ps.eFlags2 & EF2_SHIP_DEATH))
01137         {
01138                 ent->client->noCorpse = qtrue;
01139         }
01140 
01141         if (!ent->client->noCorpse && !ent->client->ps.fallingToDeath)
01142         {
01143                 if (!CopyToBodyQue (ent))
01144                 {
01145                         doRCG = qtrue;
01146                 }
01147         }
01148         else
01149         {
01150                 ent->client->noCorpse = qfalse; //clear it for next time
01151                 ent->client->ps.fallingToDeath = qfalse;
01152                 doRCG = qtrue;
01153         }
01154 
01155         if (doRCG)
01156         { //bodyque func didn't manage to call ircg so call this to assure our limbs and ragdoll states are proper on the client.
01157                 trap_SendServerCommand(-1, va("rcg %i", ent->s.clientNum));
01158         }
01159 }

team_t PickTeam int  ignoreClientNum  ) 
 

Definition at line 1291 of file g_client.c.

References level, TEAM_BLUE, TEAM_NUM_TEAMS, TEAM_RED, team_t, TeamCount(), and level_locals_t::teamScores.

Referenced by ClientBegin(), ClientUserinfoChanged(), G_InitSessionData(), and SetTeam().

01291                                        {
01292         int             counts[TEAM_NUM_TEAMS];
01293 
01294         counts[TEAM_BLUE] = TeamCount( ignoreClientNum, TEAM_BLUE );
01295         counts[TEAM_RED] = TeamCount( ignoreClientNum, TEAM_RED );
01296 
01297         if ( counts[TEAM_BLUE] > counts[TEAM_RED] ) {
01298                 return TEAM_RED;
01299         }
01300         if ( counts[TEAM_RED] > counts[TEAM_BLUE] ) {
01301                 return TEAM_BLUE;
01302         }
01303         // equal team count, so join the team with the lowest score
01304         if ( level.teamScores[TEAM_BLUE] > level.teamScores[TEAM_RED] ) {
01305                 return TEAM_RED;
01306         }
01307         return TEAM_BLUE;
01308 }

qboolean PM_RunningAnim int  anim  ) 
 

Definition at line 4601 of file bg_pmove.c.

References BOTH_RUN1, BOTH_RUN1START, BOTH_RUN1STOP, BOTH_RUN2, BOTH_RUN_DUAL, BOTH_RUN_STAFF, BOTH_RUNBACK1, BOTH_RUNBACK2, BOTH_RUNBACK_DUAL, BOTH_RUNBACK_STAFF, BOTH_RUNSTRAFE_LEFT1, BOTH_RUNSTRAFE_RIGHT1, qboolean, qfalse, and qtrue.

Referenced by BG_SetAnimFinal(), G_UpdateClientAnims(), and PM_WeaponLightsaber().

04602 {
04603         switch ( (anim) )
04604         {
04605         case BOTH_RUN1:                 
04606         case BOTH_RUN2:                 
04607         case BOTH_RUN_STAFF:
04608         case BOTH_RUN_DUAL:
04609         case BOTH_RUNBACK1:                     
04610         case BOTH_RUNBACK2:                     
04611         case BOTH_RUNBACK_STAFF:                        
04612         case BOTH_RUNBACK_DUAL:
04613         case BOTH_RUN1START:                    //# Start into full run1
04614         case BOTH_RUN1STOP:                     //# Stop from full run1
04615         case BOTH_RUNSTRAFE_LEFT1:      //# Sidestep left: should loop
04616         case BOTH_RUNSTRAFE_RIGHT1:     //# Sidestep right: should loop
04617                 return qtrue;
04618                 break;
04619         }
04620         return qfalse;
04621 }

void respawn gentity_t ent  ) 
 

Definition at line 1167 of file g_client.c.

References gentity_s::client, entityState_s::clientNum, ClientSpawn(), EV_PLAYER_TELEPORT_IN, EV_SIEGESPEC, g_gametype, g_siegeRespawn, g_siegeRespawnCheck, G_TempEntity(), gentity_t, gEscaping, GT_POWERDUEL, GT_SIEGE, gentity_s::health, gclient_s::iAmALoser, vmCvar_t::integer, level, MaintainBodyQueue(), MAX_CLIENTS, entityState_s::number, playerState_s::origin, entityState_s::owner, gclient_s::pers, gclient_s::ps, qfalse, qtrue, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, SiegeRespawn(), SPECTATOR_FREE, clientSession_t::spectatorClient, clientSession_t::spectatorState, clientSession_t::spectatorTime, STAT_HEALTH, STAT_HOLDABLE_ITEM, STAT_HOLDABLE_ITEMS, STAT_WEAPONS, playerTeamState_t::state, playerState_s::stats, gentity_s::takedamage, TEAM_BEGIN, TEAM_SPECTATOR, clientPersistant_t::teamState, gclient_s::tempSpectate, level_locals_t::time, entityState_s::time, trap_LinkEntity(), trap_UnlinkEntity(), playerState_s::weapon, and WP_NONE.

Referenced by BeginIntermission(), ClientThink_real(), G_RunFrame(), hurt_touch(), and Touch_Item().

01167                                {
01168         MaintainBodyQueue(ent);
01169 
01170         if (gEscaping || g_gametype.integer == GT_POWERDUEL)
01171         {
01172                 ent->client->sess.sessionTeam = TEAM_SPECTATOR;
01173                 ent->client->sess.spectatorState = SPECTATOR_FREE;
01174                 ent->client->sess.spectatorClient = 0;
01175 
01176                 ent->client->pers.teamState.state = TEAM_BEGIN;
01177                 ent->client->sess.spectatorTime = level.time;
01178                 ClientSpawn(ent);
01179                 ent->client->iAmALoser = qtrue;
01180                 return;
01181         }
01182 
01183         trap_UnlinkEntity (ent);
01184 
01185         if (g_gametype.integer == GT_SIEGE)
01186         {
01187                 if (g_siegeRespawn.integer)
01188                 {
01189                         if (ent->client->tempSpectate <= level.time)
01190                         {
01191                                 int minDel = g_siegeRespawn.integer* 2000;
01192                                 if (minDel < 20000)
01193                                 {
01194                                         minDel = 20000;
01195                                 }
01196                                 ent->client->tempSpectate = level.time + minDel;
01197                                 ent->health = ent->client->ps.stats[STAT_HEALTH] = 1;
01198                                 ent->client->ps.weapon = WP_NONE;
01199                                 ent->client->ps.stats[STAT_WEAPONS] = 0;
01200                                 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] = 0;
01201                                 ent->client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
01202                                 ent->takedamage = qfalse;
01203                                 trap_LinkEntity(ent);
01204 
01205                                 // Respawn time.
01206                                 if ( ent->s.number < MAX_CLIENTS )
01207                                 {
01208                                         gentity_t *te = G_TempEntity( ent->client->ps.origin, EV_SIEGESPEC );
01209                                         te->s.time = g_siegeRespawnCheck;
01210                                         te->s.owner = ent->s.number;
01211                                 }
01212 
01213                                 return;
01214                         }
01215                 }
01216                 SiegeRespawn(ent);
01217         }
01218         else
01219         {
01220                 gentity_t       *tent;
01221 
01222                 ClientSpawn(ent);
01223 
01224                 // add a teleportation effect
01225                 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
01226                 tent->s.clientNum = ent->s.clientNum;
01227         }
01228 }

gentity_t* SelectDuelSpawnPoint int  team,
vec3_t  avoidPoint,
vec3_t  origin,
vec3_t  angles
 

Definition at line 760 of file g_client.c.

References entityState_s::angles, DUELTEAM_DOUBLE, DUELTEAM_LONE, DUELTEAM_SINGLE, FOFS, G_Error(), G_Find(), gentity_t, NULL, entityState_s::origin, Q_stricmp(), random, gentity_s::s, SpotWouldTelefrag(), vec3_t, VectorCopy, and VectorSubtract.

Referenced by ClientSpawn().

00761 {
00762         gentity_t       *spot;
00763         vec3_t          delta;
00764         float           dist;
00765         float           list_dist[64];
00766         gentity_t       *list_spot[64];
00767         int                     numSpots, rnd, i, j;
00768         char            *spotName;
00769 
00770         if (team == DUELTEAM_LONE)
00771         {
00772                 spotName = "info_player_duel1";
00773         }
00774         else if (team == DUELTEAM_DOUBLE)
00775         {
00776                 spotName = "info_player_duel2";
00777         }
00778         else if (team == DUELTEAM_SINGLE)
00779         {
00780                 spotName = "info_player_duel";
00781         }
00782         else
00783         {
00784                 spotName = "info_player_deathmatch";
00785         }
00786 tryAgain:
00787 
00788         numSpots = 0;
00789         spot = NULL;
00790 
00791         while ((spot = G_Find (spot, FOFS(classname), spotName)) != NULL) {
00792                 if ( SpotWouldTelefrag( spot ) ) {
00793                         continue;
00794                 }
00795                 VectorSubtract( spot->s.origin, avoidPoint, delta );
00796                 dist = VectorLength( delta );
00797                 for (i = 0; i < numSpots; i++) {
00798                         if ( dist > list_dist[i] ) {
00799                                 if ( numSpots >= 64 )
00800                                         numSpots = 64-1;
00801                                 for (j = numSpots; j > i; j--) {
00802                                         list_dist[j] = list_dist[j-1];
00803                                         list_spot[j] = list_spot[j-1];
00804                                 }
00805                                 list_dist[i] = dist;
00806                                 list_spot[i] = spot;
00807                                 numSpots++;
00808                                 if (numSpots > 64)
00809                                         numSpots = 64;
00810                                 break;
00811                         }
00812                 }
00813                 if (i >= numSpots && numSpots < 64) {
00814                         list_dist[numSpots] = dist;
00815                         list_spot[numSpots] = spot;
00816                         numSpots++;
00817                 }
00818         }
00819         if (!numSpots)
00820         {
00821                 if (Q_stricmp(spotName, "info_player_deathmatch"))
00822                 { //try the loop again with info_player_deathmatch as the target if we couldn't find a duel spot
00823                         spotName = "info_player_deathmatch";
00824                         goto tryAgain;
00825                 }
00826 
00827                 //If we got here we found no free duel or DM spots, just try the first DM spot
00828                 spot = G_Find( NULL, FOFS(classname), "info_player_deathmatch");
00829                 if (!spot)
00830                         G_Error( "Couldn't find a spawn point" );
00831                 VectorCopy (spot->s.origin, origin);
00832                 origin[2] += 9;
00833                 VectorCopy (spot->s.angles, angles);
00834                 return spot;
00835         }
00836 
00837         // select a random spot from the spawn points furthest away
00838         rnd = random() * (numSpots / 2);
00839 
00840         VectorCopy (list_spot[rnd]->s.origin, origin);
00841         origin[2] += 9;
00842         VectorCopy (list_spot[rnd]->s.angles, angles);
00843 
00844         return list_spot[rnd];
00845 }

gentity_t* SelectInitialSpawnPoint vec3_t  origin,
vec3_t  angles,
team_t  team
 

Definition at line 894 of file g_client.c.

References entityState_s::angles, FOFS, G_Find(), gentity_t, NULL, entityState_s::origin, gentity_s::s, SelectSpawnPoint(), gentity_s::spawnflags, SpotWouldTelefrag(), team_t, vec3_origin, vec3_t, and VectorCopy.

Referenced by ClientSpawn().

00894                                                                                 {
00895         gentity_t       *spot;
00896 
00897         spot = NULL;
00898         while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
00899                 if ( spot->spawnflags & 1 ) {
00900                         break;
00901                 }
00902         }
00903 
00904         if ( !spot || SpotWouldTelefrag( spot ) ) {
00905                 return SelectSpawnPoint( vec3_origin, origin, angles, team );
00906         }
00907 
00908         VectorCopy (spot->s.origin, origin);
00909         origin[2] += 9;
00910         VectorCopy (spot->s.angles, angles);
00911 
00912         return spot;
00913 }

gentity_t* SelectNearestDeathmatchSpawnPoint vec3_t  from  ) 
 

Definition at line 590 of file g_client.c.

References FOFS, G_Find(), gentity_t, NULL, entityState_s::origin, gentity_s::s, vec3_t, and VectorSubtract.

00590                                                             {
00591         gentity_t       *spot;
00592         vec3_t          delta;
00593         float           dist, nearestDist;
00594         gentity_t       *nearestSpot;
00595 
00596         nearestDist = 999999;
00597         nearestSpot = NULL;
00598         spot = NULL;
00599 
00600         while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
00601 
00602                 VectorSubtract( spot->s.origin, from, delta );
00603                 dist = VectorLength( delta );
00604                 if ( dist < nearestDist ) {
00605                         nearestDist = dist;
00606                         nearestSpot = spot;
00607                 }
00608         }
00609 
00610         return nearestSpot;
00611 }

gentity_t* SelectRandomDeathmatchSpawnPoint void   ) 
 

Definition at line 622 of file g_client.c.

References FOFS, G_Find(), gentity_t, MAX_SPAWN_POINTS, NULL, rand(), and SpotWouldTelefrag().

00622                                                     {
00623         gentity_t       *spot;
00624         int                     count;
00625         int                     selection;
00626         gentity_t       *spots[MAX_SPAWN_POINTS];
00627 
00628         count = 0;
00629         spot = NULL;
00630 
00631         while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
00632                 if ( SpotWouldTelefrag( spot ) ) {
00633                         continue;
00634                 }
00635                 spots[ count ] = spot;
00636                 count++;
00637         }
00638 
00639         if ( !count ) { // no spots that won't telefrag
00640                 return G_Find( NULL, FOFS(classname), "info_player_deathmatch");
00641         }
00642 
00643         selection = rand() % count;
00644         return spots[ selection ];
00645 }

gentity_t* SelectRandomFurthestSpawnPoint vec3_t  avoidPoint,
vec3_t  origin,
vec3_t  angles,
team_t  team
 

Definition at line 654 of file g_client.c.

References entityState_s::angles, FOFS, G_Error(), G_Find(), g_gametype, gentity_t, GT_TEAM, vmCvar_t::integer, NULL, entityState_s::origin, random, gentity_s::s, SpotWouldTelefrag(), TEAM_FREE, TEAM_RED, TEAM_SPECTATOR, team_t, vec3_t, VectorCopy, and VectorSubtract.

Referenced by SelectSpawnPoint().

00654                                                                                                            {
00655         gentity_t       *spot;
00656         vec3_t          delta;
00657         float           dist;
00658         float           list_dist[64];
00659         gentity_t       *list_spot[64];
00660         int                     numSpots, rnd, i, j;
00661 
00662         numSpots = 0;
00663         spot = NULL;
00664 
00665         //in Team DM, look for a team start spot first, if any
00666         if ( g_gametype.integer == GT_TEAM 
00667                 && team != TEAM_FREE 
00668                 && team != TEAM_SPECTATOR )
00669         {
00670                 char *classname = NULL;
00671                 if ( team == TEAM_RED )
00672                 {
00673                         classname = "info_player_start_red";
00674                 }
00675                 else
00676                 {
00677                         classname = "info_player_start_blue";
00678                 }
00679                 while ((spot = G_Find (spot, FOFS(classname), classname)) != NULL) {
00680                         if ( SpotWouldTelefrag( spot ) ) {
00681                                 continue;
00682                         }
00683                         VectorSubtract( spot->s.origin, avoidPoint, delta );
00684                         dist = VectorLength( delta );
00685                         for (i = 0; i < numSpots; i++) {
00686                                 if ( dist > list_dist[i] ) {
00687                                         if ( numSpots >= 64 )
00688                                                 numSpots = 64-1;
00689                                         for (j = numSpots; j > i; j--) {
00690                                                 list_dist[j] = list_dist[j-1];
00691                                                 list_spot[j] = list_spot[j-1];
00692                                         }
00693                                         list_dist[i] = dist;
00694                                         list_spot[i] = spot;
00695                                         numSpots++;
00696                                         if (numSpots > 64)
00697                                                 numSpots = 64;
00698                                         break;
00699                                 }
00700                         }
00701                         if (i >= numSpots && numSpots < 64) {
00702                                 list_dist[numSpots] = dist;
00703                                 list_spot[numSpots] = spot;
00704                                 numSpots++;
00705                         }
00706                 }
00707         }
00708 
00709         if ( !numSpots )
00710         {//couldn't find any of the above
00711                 while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
00712                         if ( SpotWouldTelefrag( spot ) ) {
00713                                 continue;
00714                         }
00715                         VectorSubtract( spot->s.origin, avoidPoint, delta );
00716                         dist = VectorLength( delta );
00717                         for (i = 0; i < numSpots; i++) {
00718                                 if ( dist > list_dist[i] ) {
00719                                         if ( numSpots >= 64 )
00720                                                 numSpots = 64-1;
00721                                         for (j = numSpots; j > i; j--) {
00722                                                 list_dist[j] = list_dist[j-1];
00723                                                 list_spot[j] = list_spot[j-1];
00724                                         }
00725                                         list_dist[i] = dist;
00726                                         list_spot[i] = spot;
00727                                         numSpots++;
00728                                         if (numSpots > 64)
00729                                                 numSpots = 64;
00730                                         break;
00731                                 }
00732                         }
00733                         if (i >= numSpots && numSpots < 64) {
00734                                 list_dist[numSpots] = dist;
00735                                 list_spot[numSpots] = spot;
00736                                 numSpots++;
00737                         }
00738                 }
00739                 if (!numSpots) {
00740                         spot = G_Find( NULL, FOFS(classname), "info_player_deathmatch");
00741                         if (!spot)
00742                                 G_Error( "Couldn't find a spawn point" );
00743                         VectorCopy (spot->s.origin, origin);
00744                         origin[2] += 9;
00745                         VectorCopy (spot->s.angles, angles);
00746                         return spot;
00747                 }
00748         }
00749 
00750         // select a random spot from the spawn points furthest away
00751         rnd = random() * (numSpots / 2);
00752 
00753         VectorCopy (list_spot[rnd]->s.origin, origin);
00754         origin[2] += 9;
00755         VectorCopy (list_spot[rnd]->s.angles, angles);
00756 
00757         return list_spot[rnd];
00758 }

gentity_t* SelectSpawnPoint vec3_t  avoidPoint,
vec3_t  origin,
vec3_t  angles,
team_t  team
 

Definition at line 854 of file g_client.c.

References gentity_t, SelectRandomFurthestSpawnPoint(), team_t, and vec3_t.

Referenced by ClientSpawn(), FindIntermissionPoint(), SelectCTFSpawnPoint(), SelectInitialSpawnPoint(), and SelectSiegeSpawnPoint().

00854                                                                                              {
00855         return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles, team );
00856 
00857         /*
00858         gentity_t       *spot;
00859         gentity_t       *nearestSpot;
00860 
00861         nearestSpot = SelectNearestDeathmatchSpawnPoint( avoidPoint );
00862 
00863         spot = SelectRandomDeathmatchSpawnPoint ( );
00864         if ( spot == nearestSpot ) {
00865                 // roll again if it would be real close to point of death
00866                 spot = SelectRandomDeathmatchSpawnPoint ( );
00867                 if ( spot == nearestSpot ) {
00868                         // last try
00869                         spot = SelectRandomDeathmatchSpawnPoint ( );
00870                 }               
00871         }
00872 
00873         // find a single player start spot
00874         if (!spot) {
00875                 G_Error( "Couldn't find a spawn point" );
00876         }
00877 
00878         VectorCopy (spot->s.origin, origin);
00879         origin[2] += 9;
00880         VectorCopy (spot->s.angles, angles);
00881 
00882         return spot;
00883         */
00884 }

gentity_t* SelectSpectatorSpawnPoint vec3_t  origin,
vec3_t  angles
 

Definition at line 921 of file g_client.c.

References FindIntermissionPoint(), gentity_t, level_locals_t::intermission_angle, level_locals_t::intermission_origin, level, NULL, vec3_t, and VectorCopy.

Referenced by ClientSpawn().

00921                                                                      {
00922         FindIntermissionPoint();
00923 
00924         VectorCopy( level.intermission_origin, origin );
00925         VectorCopy( level.intermission_angle, angles );
00926 
00927         return NULL;
00928 }

void SetClientViewAngle gentity_t ent,
vec3_t  angle
 

Definition at line 1116 of file g_client.c.

References ANGLE2SHORT, usercmd_s::angles, entityState_s::angles, gentity_s::client, clientPersistant_t::cmd, playerState_s::delta_angles, gentity_t, gclient_s::pers, gclient_s::ps, gentity_s::s, vec3_t, VectorCopy, and playerState_s::viewangles.

Referenced by Board(), ClientCommand(), ClientSpawn(), ClientThink_real(), Eject(), G_HeldByMonster(), misc_weapon_shooter_aim(), NPC_Begin(), NPC_Spawn_Do(), Rancor_DropVictim(), TeleportPlayer(), and WP_SaberPositionUpdate().

01116                                                         {
01117         int                     i;
01118 
01119         // set the delta angle
01120         for (i=0 ; i<3 ; i++) {
01121                 int             cmdAngle;
01122 
01123                 cmdAngle = ANGLE2SHORT(angle[i]);
01124                 ent->client->ps.delta_angles[i] = cmdAngle - ent->client->pers.cmd.angles[i];
01125         }
01126         VectorCopy( angle, ent->s.angles );
01127         VectorCopy (ent->s.angles, ent->client->ps.viewangles);
01128 }

void SetTeamQuick gentity_t ent,
int  team,
qboolean  doBegin
 

Definition at line 787 of file g_saga.c.

References gentity_s::client, ClientBegin(), ClientUserinfoChanged(), g_gametype, G_ValidateSiegeClassForTeam(), gentity_t, GT_SIEGE, Info_SetValueForKey(), vmCvar_t::integer, MAX_INFO_STRING, entityState_s::number, gclient_s::pers, qfalse, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, SPECTATOR_FREE, SPECTATOR_NOT, clientSession_t::spectatorClient, clientSession_t::spectatorState, playerTeamState_t::state, TEAM_BEGIN, TEAM_BLUE, TEAM_RED, TEAM_SPECTATOR, clientPersistant_t::teamState, trap_GetUserinfo(), and trap_SetUserinfo().

00788 {
00789         char userinfo[MAX_INFO_STRING];
00790 
00791         trap_GetUserinfo( ent->s.number, userinfo, sizeof( userinfo ) );
00792 
00793         if (g_gametype.integer == GT_SIEGE)
00794         {
00795                 G_ValidateSiegeClassForTeam(ent, team);
00796         }
00797 
00798         ent->client->sess.sessionTeam = team;
00799 
00800         if (team == TEAM_SPECTATOR)
00801         {
00802                 ent->client->sess.spectatorState = SPECTATOR_FREE;
00803                 Info_SetValueForKey(userinfo, "team", "s");
00804         }
00805         else
00806         {
00807                 ent->client->sess.spectatorState = SPECTATOR_NOT;
00808                 if (team == TEAM_RED)
00809                 {
00810                         Info_SetValueForKey(userinfo, "team", "r");
00811                 }
00812                 else if (team == TEAM_BLUE)
00813                 {
00814                         Info_SetValueForKey(userinfo, "team", "b");
00815                 }
00816                 else
00817                 {
00818                         Info_SetValueForKey(userinfo, "team", "?");
00819                 }
00820         }
00821 
00822         trap_SetUserinfo( ent->s.number, userinfo );
00823 
00824         ent->client->sess.spectatorClient = 0;
00825 
00826         ent->client->pers.teamState.state = TEAM_BEGIN;
00827 
00828         ClientUserinfoChanged( ent->s.number );
00829 
00830         if (doBegin)
00831         {
00832                 ClientBegin( ent->s.number, qfalse );
00833         }
00834 }

void SetupGameGhoul2Model gentity_t ent,
char *  modelname,
char *  skinName
 

Definition at line 1519 of file g_client.c.

References BG_GetVehicleModelName(), BG_IsValidCharacterModel(), BG_ParseAnimationFile(), BG_ValidateSkinForTeam(), bgHumanoidAnimations, BGPAFtextLoaded, bgSiegeClasses, BONE_ANGLES_POSTMULT, BONE_ANIM_OVERRIDE_LOOP, CLASS_VEHICLE, gentity_s::client, Com_Error(), Com_Printf(), Com_sprintf(), d_perPlayerGhoul2, ERR_DROP, siegeClass_t::forcedSkin, g2SaberInstance, g_gametype, G_ModelIndex(), G_PlayerHasCustomSkeleton(), G_SaberModelSetup(), g_trueJedi, gentity_t, gentity_s::ghoul2, GT_SIEGE, GT_TEAM, turretStats_t::gunnerViewTag, vmCvar_t::integer, level, gentity_s::localAnimIndex, Vehicle_s::m_iDroidUnitTag, Vehicle_s::m_iExhaustTag, Vehicle_s::m_iGunnerViewTag, Vehicle_s::m_iMuzzleTag, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, MAX_CLIENTS, MAX_QPATH, MAX_VEHICLE_EXHAUSTS, MAX_VEHICLE_MUZZLES, MAX_VEHICLE_TURRET_MUZZLES, entityState_s::modelGhoul2, entityState_s::modelindex, NEGATIVE_Y, NEGATIVE_Z, gentity_s::noLumbar, gclient_s::NPC_class, entityState_s::NPC_class, NULL, entityState_s::number, POSITIVE_X, POSITIVE_Z, precachedKyle, gclient_s::ps, Q_strrchr(), qfalse, qtrue, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, gclient_s::siegeClass, vehicleInfo_t::skin, strcat(), strchr(), strcpy(), strstr(), level_locals_t::time, trap_G2_HaveWeGhoul2Models(), trap_G2API_AddBolt(), trap_G2API_AttachInstanceToEntNum(), trap_G2API_CleanGhoul2Models(), trap_G2API_CopySpecificGhoul2Model(), trap_G2API_DuplicateGhoul2Instance(), trap_G2API_GetGLAName(), trap_G2API_InitGhoul2Model(), trap_G2API_SetBoltInfo(), trap_G2API_SetBoneAngles(), trap_G2API_SetBoneAnim(), trap_G2API_SetSkin(), trap_R_RegisterSkin(), vehicleInfo_t::turret, va(), vec3_t, playerState_s::weapon, and WP_SABER.

Referenced by ClientBegin(), ClientUserinfoChanged(), and NPC_ParseParms().

01520 {
01521         int handle;
01522         char            afilename[MAX_QPATH];
01523 #if 0
01524         char             *slash;
01525 #endif
01526         char            GLAName[MAX_QPATH];
01527         vec3_t  tempVec = {0,0,0};
01528 
01529         // First things first.  If this is a ghoul2 model, then let's make sure we demolish this first.
01530         if (ent->ghoul2 && trap_G2_HaveWeGhoul2Models(ent->ghoul2))
01531         {
01532                 trap_G2API_CleanGhoul2Models(&(ent->ghoul2));
01533         }
01534 
01535         //rww - just load the "standard" model for the server"
01536         if (!precachedKyle)
01537         {
01538                 int defSkin;
01539 
01540                 Com_sprintf( afilename, sizeof( afilename ), "models/players/kyle/model.glm" );
01541                 handle = trap_G2API_InitGhoul2Model(&precachedKyle, afilename, 0, 0, -20, 0, 0);
01542 
01543                 if (handle<0)
01544                 {
01545                         return;
01546                 }
01547 
01548                 defSkin = trap_R_RegisterSkin("models/players/kyle/model_default.skin");
01549                 trap_G2API_SetSkin(precachedKyle, 0, defSkin, defSkin);
01550         }
01551 
01552         if (precachedKyle && trap_G2_HaveWeGhoul2Models(precachedKyle))
01553         {
01554                 if (d_perPlayerGhoul2.integer || ent->s.number >= MAX_CLIENTS ||
01555                         G_PlayerHasCustomSkeleton(ent))
01556                 { //rww - allow option for perplayer models on server for collision and bolt stuff.
01557                         char modelFullPath[MAX_QPATH];
01558                         char truncModelName[MAX_QPATH];
01559                         char skin[MAX_QPATH];
01560                         char vehicleName[MAX_QPATH];
01561                         int skinHandle = 0;
01562                         int i = 0;
01563                         char *p;
01564 
01565                         // If this is a vehicle, get it's model name.
01566                         if ( ent->client->NPC_class == CLASS_VEHICLE )
01567                         {
01568                                 strcpy(vehicleName, modelname);
01569                                 BG_GetVehicleModelName(modelname);
01570                                 strcpy(truncModelName, modelname);
01571                                 skin[0] = 0;
01572                                 if ( ent->m_pVehicle
01573                                         && ent->m_pVehicle->m_pVehicleInfo
01574                                         && ent->m_pVehicle->m_pVehicleInfo->skin
01575                                         && ent->m_pVehicle->m_pVehicleInfo->skin[0] )
01576                                 {
01577                                         skinHandle = trap_R_RegisterSkin(va("models/players/%s/model_%s.skin", modelname, ent->m_pVehicle->m_pVehicleInfo->skin));
01578                                 }
01579                                 else
01580                                 {
01581                                         skinHandle = trap_R_RegisterSkin(va("models/players/%s/model_default.skin", modelname));
01582                                 }
01583                         }
01584                         else
01585                         {
01586                                 if (skinName && skinName[0])
01587                                 {
01588                                         strcpy(skin, skinName);
01589                                         strcpy(truncModelName, modelname);
01590                                 }
01591                                 else
01592                                 {
01593                                         strcpy(skin, "default");
01594 
01595                                         strcpy(truncModelName, modelname);
01596                                         p = Q_strrchr(truncModelName, '/');
01597 
01598                                         if (p)
01599                                         {
01600                                                 *p = 0;
01601                                                 p++;
01602 
01603                                                 while (p && *p)
01604                                                 {
01605                                                         skin[i] = *p;
01606                                                         i++;
01607                                                         p++;
01608                                                 }
01609                                                 skin[i] = 0;
01610                                                 i = 0;
01611                                         }
01612 
01613                                         if (!BG_IsValidCharacterModel(truncModelName, skin))
01614                                         {
01615                                                 strcpy(truncModelName, "kyle");
01616                                                 strcpy(skin, "default");
01617                                         }
01618 
01619                                         if ( g_gametype.integer >= GT_TEAM && g_gametype.integer != GT_SIEGE && !g_trueJedi.integer )
01620                                         {
01621                                                 BG_ValidateSkinForTeam( truncModelName, skin, ent->client->sess.sessionTeam, NULL );
01622                                         }
01623                                         else if (g_gametype.integer == GT_SIEGE)
01624                                         { //force skin for class if appropriate
01625                                                 if (ent->client->siegeClass != -1)
01626                                                 {
01627                                                         siegeClass_t *scl = &bgSiegeClasses[ent->client->siegeClass];
01628                                                         if (scl->forcedSkin[0])
01629                                                         {
01630                                                                 strcpy(skin, scl->forcedSkin);
01631                                                         }
01632                                                 }
01633                                         }
01634                                 }
01635                         }
01636 
01637                         if (skin[0])
01638                         {
01639                                 char *useSkinName;
01640 
01641                                 if (strchr(skin, '|'))
01642                                 {//three part skin
01643                                         useSkinName = va("models/players/%s/|%s", truncModelName, skin);
01644                                 }
01645                                 else
01646                                 {
01647                                         useSkinName = va("models/players/%s/model_%s.skin", truncModelName, skin);
01648                                 }
01649 
01650                                 skinHandle = trap_R_RegisterSkin(useSkinName);
01651                         }
01652 
01653                         strcpy(modelFullPath, va("models/players/%s/model.glm", truncModelName));
01654                         handle = trap_G2API_InitGhoul2Model(&ent->ghoul2, modelFullPath, 0, skinHandle, -20, 0, 0);
01655 
01656                         if (handle<0)
01657                         { //Huh. Guess we don't have this model. Use the default.
01658 
01659                                 if (ent->ghoul2 && trap_G2_HaveWeGhoul2Models(ent->ghoul2))
01660                                 {
01661                                         trap_G2API_CleanGhoul2Models(&(ent->ghoul2));
01662                                 }
01663                                 ent->ghoul2 = NULL;
01664                                 trap_G2API_DuplicateGhoul2Instance(precachedKyle, &ent->ghoul2);
01665                         }
01666                         else
01667                         {
01668                                 trap_G2API_SetSkin(ent->ghoul2, 0, skinHandle, skinHandle);
01669 
01670                                 GLAName[0] = 0;
01671                                 trap_G2API_GetGLAName( ent->ghoul2, 0, GLAName);
01672 
01673                                 if (!GLAName[0] || (!strstr(GLAName, "players/_humanoid/") && ent->s.number < MAX_CLIENTS && !G_PlayerHasCustomSkeleton(ent)))
01674                                 { //a bad model
01675                                         trap_G2API_CleanGhoul2Models(&(ent->ghoul2));
01676                                         ent->ghoul2 = NULL;
01677                                         trap_G2API_DuplicateGhoul2Instance(precachedKyle, &ent->ghoul2);
01678                                 }
01679 
01680                                 if (ent->s.number >= MAX_CLIENTS)
01681                                 {
01682                                         ent->s.modelGhoul2 = 1; //so we know to free it on the client when we're removed.
01683 
01684                                         if (skin[0])
01685                                         { //append it after a *
01686                                                 strcat( modelFullPath, va("*%s", skin) );
01687                                         }
01688 
01689                                         if ( ent->client->NPC_class == CLASS_VEHICLE )
01690                                         { //vehicles are tricky and send over their vehicle names as the model (the model is then retrieved based on the vehicle name)
01691                                                 ent->s.modelindex = G_ModelIndex(vehicleName);
01692                                         }
01693                                         else
01694                                         {
01695                                                 ent->s.modelindex = G_ModelIndex(modelFullPath);
01696                                         }
01697                                 }
01698                         }
01699                 }
01700                 else
01701                 {
01702                         trap_G2API_DuplicateGhoul2Instance(precachedKyle, &ent->ghoul2);
01703                 }
01704         }
01705         else
01706         {
01707                 return;
01708         }
01709 
01710         //Attach the instance to this entity num so we can make use of client-server
01711         //shared operations if possible.
01712         trap_G2API_AttachInstanceToEntNum(ent->ghoul2, ent->s.number, qtrue);
01713 
01714         // The model is now loaded.
01715 
01716         GLAName[0] = 0;
01717 
01718         if (!BGPAFtextLoaded)
01719         {
01720                 if (BG_ParseAnimationFile("models/players/_humanoid/animation.cfg", bgHumanoidAnimations, qtrue) == -1)
01721                 {
01722                         Com_Printf( "Failed to load humanoid animation file\n");
01723                         return;
01724                 }
01725         }
01726 
01727         if (ent->s.number >= MAX_CLIENTS || G_PlayerHasCustomSkeleton(ent))
01728         {
01729                 ent->localAnimIndex = -1;
01730 
01731                 GLAName[0] = 0;
01732                 trap_G2API_GetGLAName(ent->ghoul2, 0, GLAName);
01733 
01734                 if (GLAName[0] &&
01735                         !strstr(GLAName, "players/_humanoid/") /*&&
01736                         !strstr(GLAName, "players/rockettrooper/")*/)
01737                 { //it doesn't use humanoid anims.
01738                         char *slash = Q_strrchr( GLAName, '/' );
01739                         if ( slash )
01740                         {
01741                                 strcpy(slash, "/animation.cfg");
01742 
01743                                 ent->localAnimIndex = BG_ParseAnimationFile(GLAName, NULL, qfalse);
01744                         }
01745                 }
01746                 else
01747                 { //humanoid index.
01748                         if (strstr(GLAName, "players/rockettrooper/"))
01749                         {
01750                                 ent->localAnimIndex = 1;
01751                         }
01752                         else
01753                         {
01754                                 ent->localAnimIndex = 0;
01755                         }
01756                 }
01757 
01758                 if (ent->localAnimIndex == -1)
01759                 {
01760                         Com_Error(ERR_DROP, "NPC had an invalid GLA\n");
01761                 }
01762         }
01763         else
01764         {
01765                 GLAName[0] = 0;
01766                 trap_G2API_GetGLAName(ent->ghoul2, 0, GLAName);
01767 
01768                 if (strstr(GLAName, "players/rockettrooper/"))
01769                 {
01770                         //assert(!"Should not have gotten in here with rockettrooper skel");
01771                         ent->localAnimIndex = 1;
01772                 }
01773                 else
01774                 {
01775                         ent->localAnimIndex = 0;
01776                 }
01777         }
01778 
01779         if (ent->s.NPC_class == CLASS_VEHICLE &&
01780                 ent->m_pVehicle)
01781         { //do special vehicle stuff
01782                 char strTemp[128];
01783                 int i;
01784 
01785                 // Setup the default first bolt
01786                 i = trap_G2API_AddBolt( ent->ghoul2, 0, "model_root" );
01787 
01788                 // Setup the droid unit.
01789                 ent->m_pVehicle->m_iDroidUnitTag = trap_G2API_AddBolt( ent->ghoul2, 0, "*droidunit" );
01790 
01791                 // Setup the Exhausts.
01792                 for ( i = 0; i < MAX_VEHICLE_EXHAUSTS; i++ )
01793                 {
01794                         Com_sprintf( strTemp, 128, "*exhaust%i", i + 1 );
01795                         ent->m_pVehicle->m_iExhaustTag[i] = trap_G2API_AddBolt( ent->ghoul2, 0, strTemp );
01796                 }
01797 
01798                 // Setup the Muzzles.
01799                 for ( i = 0; i < MAX_VEHICLE_MUZZLES; i++ )
01800                 {
01801                         Com_sprintf( strTemp, 128, "*muzzle%i", i + 1 );
01802                         ent->m_pVehicle->m_iMuzzleTag[i] = trap_G2API_AddBolt( ent->ghoul2, 0, strTemp );
01803                         if ( ent->m_pVehicle->m_iMuzzleTag[i] == -1 )
01804                         {//ergh, try *flash?
01805                                 Com_sprintf( strTemp, 128, "*flash%i", i + 1 );
01806                                 ent->m_pVehicle->m_iMuzzleTag[i] = trap_G2API_AddBolt( ent->ghoul2, 0, strTemp );
01807                         }
01808                 }
01809 
01810                 // Setup the Turrets.
01811                 for ( i = 0; i < MAX_VEHICLE_TURRET_MUZZLES; i++ )
01812                 {
01813                         if ( ent->m_pVehicle->m_pVehicleInfo->turret[i].gunnerViewTag )
01814                         {
01815                                 ent->m_pVehicle->m_iGunnerViewTag[i] = trap_G2API_AddBolt( ent->ghoul2, 0, ent->m_pVehicle->m_pVehicleInfo->turret[i].gunnerViewTag );
01816                         }
01817                         else
01818                         {
01819                                 ent->m_pVehicle->m_iGunnerViewTag[i] = -1;
01820                         }
01821                 }
01822         }
01823         
01824         if (ent->client->ps.weapon == WP_SABER || ent->s.number < MAX_CLIENTS)
01825         { //a player or NPC saber user
01826                 trap_G2API_AddBolt(ent->ghoul2, 0, "*r_hand");
01827                 trap_G2API_AddBolt(ent->ghoul2, 0, "*l_hand");
01828 
01829                 //rhand must always be first bolt. lhand always second. Whichever you want the
01830                 //jetpack bolted to must always be third.
01831                 trap_G2API_AddBolt(ent->ghoul2, 0, "*chestg");
01832 
01833                 //claw bolts
01834                 trap_G2API_AddBolt(ent->ghoul2, 0, "*r_hand_cap_r_arm");
01835                 trap_G2API_AddBolt(ent->ghoul2, 0, "*l_hand_cap_l_arm");
01836 
01837                 trap_G2API_SetBoneAnim(ent->ghoul2, 0, "model_root", 0, 12, BONE_ANIM_OVERRIDE_LOOP, 1.0f, level.time, -1, -1);
01838                 trap_G2API_SetBoneAngles(ent->ghoul2, 0, "upper_lumbar", tempVec, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL, 0, level.time);
01839                 trap_G2API_SetBoneAngles(ent->ghoul2, 0, "cranium", tempVec, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_Y, POSITIVE_X, NULL, 0, level.time);
01840 
01841                 if (!g2SaberInstance)
01842                 {
01843                         trap_G2API_InitGhoul2Model(&g2SaberInstance, "models/weapons2/saber/saber_w.glm", 0, 0, -20, 0, 0);
01844 
01845                         if (g2SaberInstance)
01846                         {
01847                                 // indicate we will be bolted to model 0 (ie the player) on bolt 0 (always the right hand) when we get copied
01848                                 trap_G2API_SetBoltInfo(g2SaberInstance, 0, 0);
01849                                 // now set up the gun bolt on it
01850                                 trap_G2API_AddBolt(g2SaberInstance, 0, "*blade1");
01851                         }
01852                 }
01853 
01854                 if (G_SaberModelSetup(ent))
01855                 {
01856                         if (g2SaberInstance)
01857                         {
01858                                 trap_G2API_CopySpecificGhoul2Model(g2SaberInstance, 0, ent->ghoul2, 1); 
01859                         }
01860                 }
01861         }
01862 
01863         if (ent->s.number >= MAX_CLIENTS)
01864         { //some extra NPC stuff
01865                 if (trap_G2API_AddBolt(ent->ghoul2, 0, "lower_lumbar") == -1)
01866                 { //check now to see if we have this bone for setting anims and such
01867                         ent->noLumbar = qtrue;
01868                 }
01869         }
01870 }

void SiegePointUse gentity_t self,
gentity_t other,
gentity_t activator
 

Definition at line 140 of file g_client.c.

References gentity_s::genericValue1, and gentity_t.

Referenced by SP_info_player_siegeteam1(), and SP_info_player_siegeteam2().

00141 {
00142         //Toggle the point on/off
00143         if (self->genericValue1)
00144         {
00145                 self->genericValue1 = 0;
00146         }
00147         else
00148         {
00149                 self->genericValue1 = 1;
00150         }
00151 }

void SiegeRespawn gentity_t ent  ) 
 

Definition at line 836 of file g_saga.c.

References gentity_s::client, entityState_s::clientNum, ClientSpawn(), EV_PLAYER_TELEPORT_IN, G_TempEntity(), gentity_t, playerState_s::origin, gclient_s::ps, qtrue, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, SetTeamQuick(), and clientSession_t::siegeDesiredTeam.

Referenced by respawn(), and SiegeBeginRound().

00837 {
00838         gentity_t *tent;
00839 
00840         if (ent->client->sess.sessionTeam != ent->client->sess.siegeDesiredTeam)
00841         {
00842                 SetTeamQuick(ent, ent->client->sess.siegeDesiredTeam, qtrue);
00843         }
00844         else
00845         {
00846                 ClientSpawn(ent);
00847                 // add a teleportation effect
00848                 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
00849                 tent->s.clientNum = ent->s.clientNum;
00850         }
00851 }

void SP_info_jedimaster_start gentity_t ent  ) 
 

Definition at line 476 of file g_client.c.

References gentity_s::bounceCount, gentity_s::clipmask, entityShared_t::contents, CONTENTS_TRIGGER, gentity_s::enemy, ET_MISSILE, entityState_s::eType, FL_BOUNCE_HALF, gentity_s::flags, entityState_s::g2radius, G_FreeEntity(), g_gametype, G_ModelIndex(), gentity_t, gJMSaberEnt, GT_JEDIMASTER, vmCvar_t::integer, gentity_s::isSaberEntity, JMSaberThink(), JMSaberTouch(), level, MASK_SOLID, entityShared_t::maxs, entityShared_t::mins, entityState_s::modelGhoul2, entityState_s::modelindex, gentity_s::nextthink, NULL, entityState_s::origin2, gentity_s::physicsObject, entityState_s::pos, qtrue, gentity_s::r, gentity_s::s, gentity_s::think, level_locals_t::time, gentity_s::touch, TR_GRAVITY, trap_LinkEntity(), trajectory_t::trBase, trajectory_t::trTime, trajectory_t::trType, VectorCopy, VectorSet, entityState_s::weapon, and WP_SABER.

00477 {
00478         if (g_gametype.integer != GT_JEDIMASTER)
00479         {
00480                 gJMSaberEnt = NULL;
00481                 G_FreeEntity(ent);
00482                 return;
00483         }
00484 
00485         ent->enemy = NULL;
00486 
00487         ent->flags = FL_BOUNCE_HALF;
00488 
00489         ent->s.modelindex = G_ModelIndex("models/weapons2/saber/saber_w.glm");
00490         ent->s.modelGhoul2 = 1;
00491         ent->s.g2radius = 20;
00492         //ent->s.eType = ET_GENERAL;
00493         ent->s.eType = ET_MISSILE;
00494         ent->s.weapon = WP_SABER;
00495         ent->s.pos.trType = TR_GRAVITY;
00496         ent->s.pos.trTime = level.time;
00497         VectorSet( ent->r.maxs, 3, 3, 3 );
00498         VectorSet( ent->r.mins, -3, -3, -3 );
00499         ent->r.contents = CONTENTS_TRIGGER;
00500         ent->clipmask = MASK_SOLID;
00501 
00502         ent->isSaberEntity = qtrue;
00503 
00504         ent->bounceCount = -5;
00505 
00506         ent->physicsObject = qtrue;
00507 
00508         VectorCopy(ent->s.pos.trBase, ent->s.origin2); //remember the spawn spot
00509 
00510         ent->touch = JMSaberTouch;
00511 
00512         trap_LinkEntity(ent);
00513 
00514         ent->think = JMSaberThink;
00515         ent->nextthink = level.time + 50;
00516 }

void SP_info_player_deathmatch gentity_t ent  ) 
 

Definition at line 88 of file g_client.c.

References FL_NO_BOTS, FL_NO_HUMANS, gentity_s::flags, G_SpawnInt(), and gentity_t.

Referenced by SP_info_player_siegeteam1(), SP_info_player_siegeteam2(), SP_info_player_start(), SP_info_player_start_blue(), and SP_info_player_start_red().

00088                                                  {
00089         int             i;
00090 
00091         G_SpawnInt( "nobots", "0", &i);
00092         if ( i ) {
00093                 ent->flags |= FL_NO_BOTS;
00094         }
00095         G_SpawnInt( "nohumans", "0", &i );
00096         if ( i ) {
00097                 ent->flags |= FL_NO_HUMANS;
00098         }
00099 }

void SP_info_player_duel gentity_t ent  ) 
 

Definition at line 27 of file g_client.c.

References FL_NO_BOTS, FL_NO_HUMANS, gentity_s::flags, G_SpawnInt(), and gentity_t.

00028 {
00029         int             i;
00030 
00031         G_SpawnInt( "nobots", "0", &i);
00032         if ( i ) {
00033                 ent->flags |= FL_NO_BOTS;
00034         }
00035         G_SpawnInt( "nohumans", "0", &i );
00036         if ( i ) {
00037                 ent->flags |= FL_NO_HUMANS;
00038         }
00039 }

void SP_info_player_duel1 gentity_t ent  ) 
 

Definition at line 47 of file g_client.c.

References FL_NO_BOTS, FL_NO_HUMANS, gentity_s::flags, G_SpawnInt(), and gentity_t.

00048 {
00049         int             i;
00050 
00051         G_SpawnInt( "nobots", "0", &i);
00052         if ( i ) {
00053                 ent->flags |= FL_NO_BOTS;
00054         }
00055         G_SpawnInt( "nohumans", "0", &i );
00056         if ( i ) {
00057                 ent->flags |= FL_NO_HUMANS;
00058         }
00059 }

void SP_info_player_duel2 gentity_t ent  ) 
 

Definition at line 67 of file g_client.c.

References FL_NO_BOTS, FL_NO_HUMANS, gentity_s::flags, G_SpawnInt(), and gentity_t.

00068 {
00069         int             i;
00070 
00071         G_SpawnInt( "nobots", "0", &i);
00072         if ( i ) {
00073                 ent->flags |= FL_NO_BOTS;
00074         }
00075         G_SpawnInt( "nohumans", "0", &i );
00076         if ( i ) {
00077                 ent->flags |= FL_NO_HUMANS;
00078         }
00079 }

void SP_info_player_intermission gentity_t ent  ) 
 

Definition at line 230 of file g_client.c.

References gentity_t.

00230                                                    {
00231 
00232 }

void SP_info_player_intermission_blue gentity_t ent  ) 
 

Definition at line 252 of file g_client.c.

References gentity_t.

00252                                                         {
00253 
00254 }

void SP_info_player_intermission_red gentity_t ent  ) 
 

Definition at line 241 of file g_client.c.

References gentity_t.

00241                                                        {
00242 
00243 }

void SP_info_player_siegeteam1 gentity_t ent  ) 
 

Definition at line 164 of file g_client.c.

References gentity_s::classname, g_gametype, G_SpawnInt(), gentity_s::genericValue1, gentity_t, GT_SIEGE, vmCvar_t::integer, SiegePointUse(), SP_info_player_deathmatch(), and gentity_s::use.

00164                                                {
00165         int soff = 0;
00166 
00167         if (g_gametype.integer != GT_SIEGE)
00168         { //turn into a DM spawn if not in siege game mode
00169                 ent->classname = "info_player_deathmatch";
00170                 SP_info_player_deathmatch( ent );
00171 
00172                 return;
00173         }
00174 
00175         G_SpawnInt("startoff", "0", &soff);
00176 
00177         if (soff)
00178         { //start disabled
00179                 ent->genericValue1 = 0;
00180         }
00181         else
00182         {
00183                 ent->genericValue1 = 1;
00184         }
00185 
00186         ent->use = SiegePointUse;
00187 }

void SP_info_player_siegeteam2 gentity_t ent  ) 
 

Definition at line 200 of file g_client.c.

References gentity_s::classname, g_gametype, G_SpawnInt(), gentity_s::genericValue1, gentity_t, GT_SIEGE, vmCvar_t::integer, SiegePointUse(), SP_info_player_deathmatch(), and gentity_s::use.

00200                                                {
00201         int soff = 0;
00202 
00203         if (g_gametype.integer != GT_SIEGE)
00204         { //turn into a DM spawn if not in siege game mode
00205                 ent->classname = "info_player_deathmatch";
00206                 SP_info_player_deathmatch( ent );
00207 
00208                 return;
00209         }
00210 
00211         G_SpawnInt("startoff", "0", &soff);
00212 
00213         if (soff)
00214         { //start disabled
00215                 ent->genericValue1 = 0;
00216         }
00217         else
00218         {
00219                 ent->genericValue1 = 1;
00220         }
00221 
00222         ent->use = SiegePointUse;
00223 }

void SP_info_player_start gentity_t ent  ) 
 

Definition at line 105 of file g_client.c.

References gentity_s::classname, gentity_t, and SP_info_player_deathmatch().

00105                                           {
00106         ent->classname = "info_player_deathmatch";
00107         SP_info_player_deathmatch( ent );
00108 }

void SP_info_player_start_blue gentity_t ent  ) 
 

Definition at line 136 of file g_client.c.

References gentity_t, and SP_info_player_deathmatch().

00136                                                {
00137         SP_info_player_deathmatch( ent );
00138 }

void SP_info_player_start_red gentity_t ent  ) 
 

Definition at line 121 of file g_client.c.

References gentity_t, and SP_info_player_deathmatch().

00121                                               {
00122         SP_info_player_deathmatch( ent );
00123 }

qboolean SpotWouldTelefrag gentity_t spot  ) 
 

Definition at line 532 of file g_client.c.

References gentity_s::client, g_entities, gentity_t, MAX_GENTITIES, entityState_s::origin, playerMaxs, playerMins, qboolean, qfalse, qtrue, gentity_s::s, trap_EntitiesInBox(), vec3_t, and VectorAdd.

Referenced by SelectDuelSpawnPoint(), SelectInitialSpawnPoint(), SelectRandomDeathmatchSpawnPoint(), SelectRandomFurthestSpawnPoint(), and SelectRandomTeamSpawnPoint().

00532                                               {
00533         int                     i, num;
00534         int                     touch[MAX_GENTITIES];
00535         gentity_t       *hit;
00536         vec3_t          mins, maxs;
00537 
00538         VectorAdd( spot->s.origin, playerMins, mins );
00539         VectorAdd( spot->s.origin, playerMaxs, maxs );
00540         num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
00541 
00542         for (i=0 ; i<num ; i++) {
00543                 hit = &g_entities[touch[i]];
00544                 //if ( hit->client && hit->client->ps.stats[STAT_HEALTH] > 0 ) {
00545                 if ( hit->client) {
00546                         return qtrue;
00547                 }
00548 
00549         }
00550 
00551         return qfalse;
00552 }

qboolean SpotWouldTelefrag2 gentity_t mover,
vec3_t  dest
 

Definition at line 554 of file g_client.c.

References entityShared_t::contents, g_entities, gentity_t, MAX_GENTITIES, entityShared_t::maxs, entityShared_t::mins, qboolean, qfalse, qtrue, gentity_s::r, trap_EntitiesInBox(), vec3_t, and VectorAdd.

Referenced by MoveOwner(), and SolidifyOwner().

00555 {
00556         int                     i, num;
00557         int                     touch[MAX_GENTITIES];
00558         gentity_t       *hit;
00559         vec3_t          mins, maxs;
00560 
00561         VectorAdd( dest, mover->r.mins, mins );
00562         VectorAdd( dest, mover->r.maxs, maxs );
00563         num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
00564 
00565         for (i=0 ; i<num ; i++) 
00566         {
00567                 hit = &g_entities[touch[i]];
00568                 if ( hit == mover )
00569                 {
00570                         continue;
00571                 }
00572 
00573                 if ( hit->r.contents & mover->r.contents )
00574                 {
00575                         return qtrue;
00576                 }
00577         }
00578 
00579         return qfalse;
00580 }

team_t TeamCount int  ignoreClientNum,
int  team
 

Definition at line 1237 of file g_client.c.

References level_locals_t::clients, CON_DISCONNECTED, clientPersistant_t::connected, g_gametype, GT_SIEGE, vmCvar_t::integer, level, level_locals_t::maxclients, gclient_s::pers, gclient_s::sess, clientSession_t::sessionTeam, clientSession_t::siegeDesiredTeam, and team_t.

Referenced by CheckTournament(), PickTeam(), and SetTeam().

01237                                                   {
01238         int             i;
01239         int             count = 0;
01240 
01241         for ( i = 0 ; i < level.maxclients ; i++ ) {
01242                 if ( i == ignoreClientNum ) {
01243                         continue;
01244                 }
01245                 if ( level.clients[i].pers.connected == CON_DISCONNECTED ) {
01246                         continue;
01247                 }
01248                 if ( level.clients[i].sess.sessionTeam == team ) {
01249                         count++;
01250                 }
01251                 else if (g_gametype.integer == GT_SIEGE &&
01252             level.clients[i].sess.siegeDesiredTeam == team)
01253                 {
01254                         count++;
01255                 }
01256         }
01257 
01258         return count;
01259 }

int TeamLeader int  team  ) 
 

Definition at line 1268 of file g_client.c.

References level_locals_t::clients, CON_DISCONNECTED, clientPersistant_t::connected, level, level_locals_t::maxclients, gclient_s::pers, gclient_s::sess, clientSession_t::sessionTeam, and clientSession_t::teamLeader.

Referenced by SetTeam().

01268                            {
01269         int             i;
01270 
01271         for ( i = 0 ; i < level.maxclients ; i++ ) {
01272                 if ( level.clients[i].pers.connected == CON_DISCONNECTED ) {
01273                         continue;
01274                 }
01275                 if ( level.clients[i].sess.sessionTeam == team ) {
01276                         if ( level.clients[i].sess.teamLeader )
01277                                 return i;
01278                 }
01279         }
01280 
01281         return -1;
01282 }

void ThrowSaberToAttacker gentity_t self,
gentity_t attacker
 

Definition at line 258 of file g_client.c.

References entityState_s::apos, gentity_s::client, Com_Printf(), CS_CLIENT_JEDIMASTER, entityShared_t::currentAngles, entityShared_t::currentOrigin, EF_NODRAW, entityState_s::eFlags, gentity_s::enemy, ET_MISSILE, entityState_s::eType, g_entities, gentity_t, gJMSaberEnt, gentity_s::inuse, saberInfo_t::model, entityState_s::modelGhoul2, NULL, entityState_s::number, entityState_s::origin, playerState_s::origin, entityState_s::origin2, entityState_s::pos, gentity_s::pos2, gclient_s::ps, qtrue, gentity_s::r, gentity_s::s, gclient_s::saber, playerState_s::saberEntityNum, playerState_s::saberIndex, playerState_s::saberInFlight, saberInfo_t::skin, trap_LinkEntity(), trap_SetConfigstring(), trajectory_t::trBase, trajectory_t::trDelta, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, and WP_SaberAddG2Model().

Referenced by player_die().

00259 {
00260         gentity_t *ent = &g_entities[self->client->ps.saberIndex];
00261         vec3_t a;
00262         int altVelocity = 0;
00263 
00264         if (!ent || ent->enemy != self)
00265         { //something has gone very wrong (this should never happen)
00266                 //but in case it does.. find the saber manually
00267 #ifdef _DEBUG
00268                 Com_Printf("Lost the saber! Attempting to use global pointer..\n");
00269 #endif
00270                 ent = gJMSaberEnt;
00271 
00272                 if (!ent)
00273                 {
00274 #ifdef _DEBUG
00275                         Com_Printf("The global pointer was NULL. This is a bad thing.\n");
00276 #endif
00277                         return;
00278                 }
00279 
00280 #ifdef _DEBUG
00281                 Com_Printf("Got it (%i). Setting enemy to client %i.\n", ent->s.number, self->s.number);
00282 #endif
00283 
00284                 ent->enemy = self;
00285                 self->client->ps.saberIndex = ent->s.number;
00286         }
00287 
00288         trap_SetConfigstring ( CS_CLIENT_JEDIMASTER, "-1" );
00289 
00290         if (attacker && attacker->client && self->client->ps.saberInFlight)
00291         { //someone killed us and we had the saber thrown, so actually move this saber to the saber location
00292           //if we killed ourselves with saber thrown, however, same suicide rules of respawning at spawn spot still
00293           //apply.
00294                 gentity_t *flyingsaber = &g_entities[self->client->ps.saberEntityNum];
00295 
00296                 if (flyingsaber && flyingsaber->inuse)
00297                 {
00298                         VectorCopy(flyingsaber->s.pos.trBase, ent->s.pos.trBase);
00299                         VectorCopy(flyingsaber->s.pos.trDelta, ent->s.pos.trDelta);
00300                         VectorCopy(flyingsaber->s.apos.trBase, ent->s.apos.trBase);
00301                         VectorCopy(flyingsaber->s.apos.trDelta, ent->s.apos.trDelta);
00302 
00303                         VectorCopy(flyingsaber->r.currentOrigin, ent->r.currentOrigin);
00304                         VectorCopy(flyingsaber->r.currentAngles, ent->r.currentAngles);
00305                         altVelocity = 1;
00306                 }
00307         }
00308 
00309         self->client->ps.saberInFlight = qtrue; //say he threw it anyway in order to properly remove from dead body
00310 
00311         WP_SaberAddG2Model( ent, self->client->saber[0].model, self->client->saber[0].skin );
00312 
00313         ent->s.eFlags &= ~(EF_NODRAW);
00314         ent->s.modelGhoul2 = 1;
00315         ent->s.eType = ET_MISSILE;
00316         ent->enemy = NULL;
00317 
00318         if (!attacker || !attacker->client)
00319         {
00320                 VectorCopy(ent->s.origin2, ent->s.pos.trBase);
00321                 VectorCopy(ent->s.origin2, ent->s.origin);
00322                 VectorCopy(ent->s.origin2, ent->r.currentOrigin);
00323                 ent->pos2[0] = 0;
00324                 trap_LinkEntity(ent);
00325                 return;
00326         }
00327 
00328         if (!altVelocity)
00329         {
00330                 VectorCopy(self->s.pos.trBase, ent->s.pos.trBase);
00331                 VectorCopy(self->s.pos.trBase, ent->s.origin);
00332                 VectorCopy(self->s.pos.trBase, ent->r.currentOrigin);
00333 
00334                 VectorSubtract(attacker->client->ps.origin, ent->s.pos.trBase, a);
00335 
00336                 VectorNormalize(a);
00337 
00338                 ent->s.pos.trDelta[0] = a[0]*256;
00339                 ent->s.pos.trDelta[1] = a[1]*256;
00340                 ent->s.pos.trDelta[2] = 256;
00341         }
00342 
00343         trap_LinkEntity(ent);
00344 }

qboolean WP_HasForcePowers const playerState_t ps  ) 
 

Definition at line 5004 of file w_force.c.

References playerState_s::fd, FORCE_LEVEL_0, FORCE_LEVEL_1, forcedata_s::forcePowerLevel, FP_LEVITATION, NUM_FORCE_POWERS, playerState_t, qboolean, qfalse, and qtrue.

Referenced by ClientSpawn().

05005 {
05006         int i;
05007         if ( ps )
05008         {
05009                 for ( i = 0; i < NUM_FORCE_POWERS; i++ )
05010                 {
05011                         if ( i == FP_LEVITATION )
05012                         {
05013                                 if ( ps->fd.forcePowerLevel[i] > FORCE_LEVEL_1 )
05014                                 {
05015                                         return qtrue;
05016                                 }
05017                         }
05018                         else if ( ps->fd.forcePowerLevel[i] > FORCE_LEVEL_0 )
05019                         {
05020                                 return qtrue;
05021                         }
05022                 }
05023         }
05024         return qfalse;
05025 }

void WP_SaberAddG2Model gentity_t saberent,
const char *  saberModel,
qhandle_t  saberSkin
 

Definition at line 6595 of file w_saber.c.

References G_ModelIndex(), gentity_t, gentity_s::ghoul2, entityState_s::modelindex, qhandle_t, gentity_s::s, trap_G2API_InitGhoul2Model(), and WP_SaberRemoveG2Model().

06596 {
06597         WP_SaberRemoveG2Model( saberent );
06598         if ( saberModel && saberModel[0] )
06599         {
06600                 saberent->s.modelindex = G_ModelIndex(saberModel);
06601         }
06602         else
06603         {
06604                 saberent->s.modelindex = G_ModelIndex( "models/weapons2/saber/saber_w.glm" );
06605         }
06606         //FIXME: use customSkin?
06607         trap_G2API_InitGhoul2Model( &saberent->ghoul2, saberModel, saberent->s.modelindex, saberSkin, 0, 0, 0 );
06608 }

void WP_SaberRemoveG2Model gentity_t saberent  ) 
 

Definition at line 6587 of file w_saber.c.

References gentity_t, gentity_s::ghoul2, and trap_G2API_RemoveGhoul2Models().

06588 {
06589         if ( saberent->ghoul2 )
06590         {
06591                 trap_G2API_RemoveGhoul2Models( &saberent->ghoul2 );
06592         }
06593 }

qboolean WP_SaberStyleValidForSaber saberInfo_t saber1,
saberInfo_t saber2,
int  saberHolstered,
int  saberAnimLevel
 

Definition at line 353 of file bg_saberLoad.c.

00354 {
00355         qboolean saber1Active;
00356         qboolean saber2Active;
00357         qboolean dualSabers = qfalse;
00358 
00359         if ( saber2 && saber2->model && saber2->model[0] )
00360         {
00361                 dualSabers = qtrue;
00362         }
00363 
00364         if ( dualSabers )
00365         {//dual
00366                 if ( saberHolstered > 1 )
00367                 {
00368                         saber1Active = saber2Active = qfalse;
00369                 }
00370                 else if ( saberHolstered > 0 )
00371                 {
00372                         saber1Active = qtrue;
00373                         saber2Active = qfalse;
00374                 }
00375                 else
00376                 {
00377                         saber1Active = saber2Active = qtrue;
00378                 }
00379         }
00380         else
00381         {
00382                 saber2Active = qfalse;
00383                 if ( !saber1
00384                         || !saber1->model
00385                         || !saber1->model[0] )
00386                 {
00387                         saber1Active = qfalse;
00388                 }
00389                 else if ( saber1->numBlades > 1 )
00390                 {//staff
00391                         if ( saberHolstered > 1 )
00392                         {
00393                                 saber1Active = qfalse;
00394                         }
00395                         else
00396                         {
00397                                 saber1Active = qtrue;
00398                         }
00399                 }
00400                 else
00401                 {//single
00402                         if ( saberHolstered )
00403                         {
00404                                 saber1Active = qfalse;
00405                         }
00406                         else
00407                         {
00408                                 saber1Active = qtrue;
00409                         }
00410                 }
00411         }
00412 
00413         if ( saber1Active
00414                 && saber1
00415                 && saber1->model
00416                 && saber1->model[0]
00417                 && saber1->stylesForbidden )
00418         {
00419                 if ( (saber1->stylesForbidden&(1<<saberAnimLevel)) )
00420                 {//not a valid style for first saber!
00421                         return qfalse;
00422                 }
00423         }
00424         if ( dualSabers
00425                 && saber2Active
00426                 && saber2
00427                 && saber2->model
00428                 && saber2->model[0] )
00429         {
00430                 if ( saber2->stylesForbidden )
00431                 {//check second saber, too
00432                         if ( (saber2->stylesForbidden&(1<<saberAnimLevel)) )
00433                         {//not a valid style for second saber!
00434                                 return qfalse;
00435                         }
00436                 }
00437                 //now: if using dual sabers, only dual and tavion (if given with this saber) are allowed
00438                 if ( saberAnimLevel != SS_DUAL )
00439                 {//dual is okay
00440                         if ( saberAnimLevel != SS_TAVION )
00441                         {//tavion might be okay, all others are not
00442                                 return qfalse;
00443                         }
00444                         else
00445                         {//see if "tavion" style is okay
00446                                 if ( saber1Active
00447                                         && saber1
00448                                         && saber1->model
00449                                         && saber1->model[0]
00450                                         && (saber1->stylesLearned&(1<<SS_TAVION)) )
00451                                 {//okay to use tavion style, first saber gave it to us
00452                                 }
00453                                 else if ( (saber2->stylesLearned&(1<<SS_TAVION)) )
00454                                 {//okay to use tavion style, second saber gave it to us
00455                                 }
00456                                 else
00457                                 {//tavion style is not allowed because neither of the sabers we're using gave it to us (I know, doesn't quite make sense, but...)
00458                                         return qfalse;
00459                                 }
00460                         }
00461                 }
00462         }
00463         return qtrue;
00464 }

void WP_SetSaber int  entNum,
saberInfo_t sabers,
int  saberNum,
const char *  saberName
 

Definition at line 2690 of file bg_saberLoad.c.

02691 {
02692         if ( !sabers )
02693         {
02694                 return;
02695         }
02696         if ( Q_stricmp( "none", saberName ) == 0 || Q_stricmp( "remove", saberName ) == 0 )
02697         {
02698                 if (saberNum != 0)
02699                 { //can't remove saber 0 ever
02700                         WP_RemoveSaber( sabers, saberNum );
02701                 }
02702                 return;
02703         }
02704 
02705         if ( entNum < MAX_CLIENTS &&
02706                 !WP_SaberValidForPlayerInMP( saberName ) )
02707         {
02708                 WP_SaberParseParms( "Kyle", &sabers[saberNum] );//get saber info
02709         }
02710         else
02711         {
02712                 WP_SaberParseParms( saberName, &sabers[saberNum] );//get saber info
02713         }
02714         if ((sabers[1].saberFlags&SFL_TWO_HANDED))
02715         {//not allowed to use a 2-handed saber as second saber
02716                 WP_RemoveSaber( sabers, 1 );
02717                 return;
02718         }
02719         else if ((sabers[0].saberFlags&SFL_TWO_HANDED) &&
02720                 sabers[1].model[0])
02721         { //you can't use a two-handed saber with a second saber, so remove saber 2
02722                 WP_RemoveSaber( sabers, 1 );
02723                 return;
02724         }
02725 }

qboolean WP_UseFirstValidSaberStyle saberInfo_t saber1,
saberInfo_t saber2,
int  saberHolstered,
int *  saberAnimLevel
 

Definition at line 245 of file bg_saberLoad.c.

00246 {
00247         qboolean styleInvalid = qfalse;
00248         qboolean saber1Active;
00249         qboolean saber2Active;
00250         qboolean dualSabers = qfalse;
00251         int     validStyles = 0, styleNum;
00252 
00253         if ( saber2 && saber2->model && saber2->model[0] )
00254         {
00255                 dualSabers = qtrue;
00256         }
00257 
00258         if ( dualSabers )
00259         {//dual
00260                 if ( saberHolstered > 1 )
00261                 {
00262                         saber1Active = saber2Active = qfalse;
00263                 }
00264                 else if ( saberHolstered > 0 )
00265                 {
00266                         saber1Active = qtrue;
00267                         saber2Active = qfalse;
00268                 }
00269                 else
00270                 {
00271                         saber1Active = saber2Active = qtrue;
00272                 }
00273         }
00274         else
00275         {
00276                 saber2Active = qfalse;
00277                 if ( !saber1
00278                         || !saber1->model
00279                         || !saber1->model[0] )
00280                 {
00281                         saber1Active = qfalse;
00282                 }
00283                 else if ( saber1->numBlades > 1 )
00284                 {//staff
00285                         if ( saberHolstered > 1 )
00286                         {
00287                                 saber1Active = qfalse;
00288                         }
00289                         else
00290                         {
00291                                 saber1Active = qtrue;
00292                         }
00293                 }
00294                 else
00295                 {//single
00296                         if ( saberHolstered )
00297                         {
00298                                 saber1Active = qfalse;
00299                         }
00300                         else
00301                         {
00302                                 saber1Active = qtrue;
00303                         }
00304                 }
00305         }
00306 
00307         //initially, all styles are valid
00308         for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
00309         {
00310                 validStyles |= (1<<styleNum);
00311         }
00312 
00313         if ( saber1Active
00314                 && saber1
00315                 && saber1->model
00316                 && saber1->model[0]
00317                 && saber1->stylesForbidden )
00318         {
00319                 if ( (saber1->stylesForbidden&(1<<*saberAnimLevel)) )
00320                 {//not a valid style for first saber!
00321                         styleInvalid = qtrue;
00322                         validStyles &= ~saber1->stylesForbidden;
00323                 }
00324         }
00325         if ( dualSabers )
00326         {//check second saber, too
00327                 if ( saber2Active
00328                         && saber2->stylesForbidden )
00329                 {
00330                         if ( (saber2->stylesForbidden&(1<<*saberAnimLevel)) )
00331                         {//not a valid style for second saber!
00332                                 styleInvalid = qtrue;
00333                                 //only the ones both sabers allow is valid
00334                                 validStyles &= ~saber2->stylesForbidden;
00335                         }
00336                 }
00337         }
00338         if ( styleInvalid && validStyles )
00339         {//using an invalid style and have at least one valid style to use, so switch to it
00340                 int styleNum;
00341                 for ( styleNum = SS_FAST; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
00342                 {
00343                         if ( (validStyles&(1<<styleNum)) )
00344                         {
00345                                 *saberAnimLevel = styleNum;
00346                                 return qtrue;
00347                         }
00348                 }
00349         }
00350         return qfalse;
00351 }


Variable Documentation

forcedata_t Client_Force[MAX_CLIENTS]
 

Definition at line 19 of file g_client.c.

void* g2SaberInstance = NULL
 

Definition at line 1511 of file g_client.c.

Referenced by G_ShutdownGame(), SetupGameGhoul2Model(), SP_worldspawn(), and WP_SaberPositionUpdate().

int g_siegeRespawnCheck
 

Definition at line 12 of file g_client.c.

Referenced by G_RunFrame(), and respawn().

gentity_t* gJMSaberEnt = NULL
 

Definition at line 471 of file g_client.c.

Referenced by JMSaberThink(), JMTakesPriority(), SP_info_jedimaster_start(), StandardBotAI(), and ThrowSaberToAttacker().

qboolean gSiegeRoundBegun
 

Definition at line 2382 of file g_client.c.

Referenced by ClientBegin(), G_Damage(), multi_trigger(), SiegeCheckTimers(), SiegeItemTouch(), SiegeRoundComplete(), and TryUse().

qboolean gSiegeRoundEnded
 

Definition at line 2383 of file g_client.c.

Referenced by ClientBegin(), decompTriggerUse(), FindIntermissionPoint(), SiegeCheckTimers(), SiegeObjectiveCompleted(), and SiegeRoundComplete().