00001
00002
00003 #include "g_local.h"
00004 #include "bg_saga.h"
00005
00006 #include "../../ui/menudef.h"
00007
00008
00009 int AcceptBotCommand(char *cmd, gentity_t *pl);
00010
00011
00012 #include "../namespace_begin.h"
00013 void WP_SetSaber( int entNum, saberInfo_t *sabers, int saberNum, const char *saberName );
00014 #include "../namespace_end.h"
00015
00016 void Cmd_NPC_f( gentity_t *ent );
00017 void SetTeamQuick(gentity_t *ent, int team, qboolean doBegin);
00018
00019
00020
00021
00022
00023
00024
00025 void DeathmatchScoreboardMessage( gentity_t *ent ) {
00026 char entry[1024];
00027 char string[1400];
00028 int stringlength;
00029 int i, j;
00030 gclient_t *cl;
00031 int numSorted, scoreFlags, accuracy, perfect;
00032
00033
00034 string[0] = 0;
00035 stringlength = 0;
00036 scoreFlags = 0;
00037
00038 numSorted = level.numConnectedClients;
00039
00040 if (numSorted > MAX_CLIENT_SCORE_SEND)
00041 {
00042 numSorted = MAX_CLIENT_SCORE_SEND;
00043 }
00044
00045 for (i=0 ; i < numSorted ; i++) {
00046 int ping;
00047
00048 cl = &level.clients[level.sortedClients[i]];
00049
00050 if ( cl->pers.connected == CON_CONNECTING ) {
00051 ping = -1;
00052 } else {
00053 ping = cl->ps.ping < 999 ? cl->ps.ping : 999;
00054 }
00055
00056 if( cl->accuracy_shots ) {
00057 accuracy = cl->accuracy_hits * 100 / cl->accuracy_shots;
00058 }
00059 else {
00060 accuracy = 0;
00061 }
00062 perfect = ( cl->ps.persistant[PERS_RANK] == 0 && cl->ps.persistant[PERS_KILLED] == 0 ) ? 1 : 0;
00063
00064 Com_sprintf (entry, sizeof(entry),
00065 " %i %i %i %i %i %i %i %i %i %i %i %i %i %i", level.sortedClients[i],
00066 cl->ps.persistant[PERS_SCORE], ping, (level.time - cl->pers.enterTime)/60000,
00067 scoreFlags, g_entities[level.sortedClients[i]].s.powerups, accuracy,
00068 cl->ps.persistant[PERS_IMPRESSIVE_COUNT],
00069 cl->ps.persistant[PERS_EXCELLENT_COUNT],
00070 cl->ps.persistant[PERS_GAUNTLET_FRAG_COUNT],
00071 cl->ps.persistant[PERS_DEFEND_COUNT],
00072 cl->ps.persistant[PERS_ASSIST_COUNT],
00073 perfect,
00074 cl->ps.persistant[PERS_CAPTURES]);
00075 j = strlen(entry);
00076 if (stringlength + j > 1022)
00077 break;
00078 strcpy (string + stringlength, entry);
00079 stringlength += j;
00080 }
00081
00082
00083 i = level.numConnectedClients;
00084
00085 trap_SendServerCommand( ent-g_entities, va("scores %i %i %i%s", i,
00086 level.teamScores[TEAM_RED], level.teamScores[TEAM_BLUE],
00087 string ) );
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 void Cmd_Score_f( gentity_t *ent ) {
00099 DeathmatchScoreboardMessage( ent );
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109 qboolean CheatsOk( gentity_t *ent ) {
00110 if ( !g_cheats.integer ) {
00111 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOCHEATS")));
00112 return qfalse;
00113 }
00114 if ( ent->health <= 0 ) {
00115 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "MUSTBEALIVE")));
00116 return qfalse;
00117 }
00118 return qtrue;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 char *ConcatArgs( int start ) {
00128 int i, c, tlen;
00129 static char line[MAX_STRING_CHARS];
00130 int len;
00131 char arg[MAX_STRING_CHARS];
00132
00133 len = 0;
00134 c = trap_Argc();
00135 for ( i = start ; i < c ; i++ ) {
00136 trap_Argv( i, arg, sizeof( arg ) );
00137 tlen = strlen( arg );
00138 if ( len + tlen >= MAX_STRING_CHARS - 1 ) {
00139 break;
00140 }
00141 memcpy( line + len, arg, tlen );
00142 len += tlen;
00143 if ( i != c - 1 ) {
00144 line[len] = ' ';
00145 len++;
00146 }
00147 }
00148
00149 line[len] = 0;
00150
00151 return line;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161 void SanitizeString( char *in, char *out ) {
00162 while ( *in ) {
00163 if ( *in == 27 ) {
00164 in += 2;
00165 continue;
00166 }
00167 if ( *in < 32 ) {
00168 in++;
00169 continue;
00170 }
00171 *out++ = tolower( (unsigned char) *in++ );
00172 }
00173
00174 *out = 0;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 int ClientNumberFromString( gentity_t *to, char *s ) {
00186 gclient_t *cl;
00187 int idnum;
00188 char s2[MAX_STRING_CHARS];
00189 char n2[MAX_STRING_CHARS];
00190
00191
00192 if (s[0] >= '0' && s[0] <= '9') {
00193 idnum = atoi( s );
00194 if ( idnum < 0 || idnum >= level.maxclients ) {
00195 trap_SendServerCommand( to-g_entities, va("print \"Bad client slot: %i\n\"", idnum));
00196 return -1;
00197 }
00198
00199 cl = &level.clients[idnum];
00200 if ( cl->pers.connected != CON_CONNECTED ) {
00201 trap_SendServerCommand( to-g_entities, va("print \"Client %i is not active\n\"", idnum));
00202 return -1;
00203 }
00204 return idnum;
00205 }
00206
00207
00208 SanitizeString( s, s2 );
00209 for ( idnum=0,cl=level.clients ; idnum < level.maxclients ; idnum++,cl++ ) {
00210 if ( cl->pers.connected != CON_CONNECTED ) {
00211 continue;
00212 }
00213 SanitizeString( cl->pers.netname, n2 );
00214 if ( !strcmp( n2, s2 ) ) {
00215 return idnum;
00216 }
00217 }
00218
00219 trap_SendServerCommand( to-g_entities, va("print \"User %s is not on the server\n\"", s));
00220 return -1;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 void Cmd_Give_f (gentity_t *cmdent, int baseArg)
00231 {
00232 char name[MAX_TOKEN_CHARS];
00233 gentity_t *ent;
00234 gitem_t *it;
00235 int i;
00236 qboolean give_all;
00237 gentity_t *it_ent;
00238 trace_t trace;
00239 char arg[MAX_TOKEN_CHARS];
00240
00241 if ( !CheatsOk( cmdent ) ) {
00242 return;
00243 }
00244
00245 if (baseArg)
00246 {
00247 char otherindex[MAX_TOKEN_CHARS];
00248
00249 trap_Argv( 1, otherindex, sizeof( otherindex ) );
00250
00251 if (!otherindex[0])
00252 {
00253 Com_Printf("giveother requires that the second argument be a client index number.\n");
00254 return;
00255 }
00256
00257 i = atoi(otherindex);
00258
00259 if (i < 0 || i >= MAX_CLIENTS)
00260 {
00261 Com_Printf("%i is not a client index\n", i);
00262 return;
00263 }
00264
00265 ent = &g_entities[i];
00266
00267 if (!ent->inuse || !ent->client)
00268 {
00269 Com_Printf("%i is not an active client\n", i);
00270 return;
00271 }
00272 }
00273 else
00274 {
00275 ent = cmdent;
00276 }
00277
00278 trap_Argv( 1+baseArg, name, sizeof( name ) );
00279
00280 if (Q_stricmp(name, "all") == 0)
00281 give_all = qtrue;
00282 else
00283 give_all = qfalse;
00284
00285 if (give_all)
00286 {
00287 i = 0;
00288 while (i < HI_NUM_HOLDABLE)
00289 {
00290 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] |= (1 << i);
00291 i++;
00292 }
00293 i = 0;
00294 }
00295
00296 if (give_all || Q_stricmp( name, "health") == 0)
00297 {
00298 if (trap_Argc() == 3+baseArg) {
00299 trap_Argv( 2+baseArg, arg, sizeof( arg ) );
00300 ent->health = atoi(arg);
00301 if (ent->health > ent->client->ps.stats[STAT_MAX_HEALTH]) {
00302 ent->health = ent->client->ps.stats[STAT_MAX_HEALTH];
00303 }
00304 }
00305 else {
00306 ent->health = ent->client->ps.stats[STAT_MAX_HEALTH];
00307 }
00308 if (!give_all)
00309 return;
00310 }
00311
00312 if (give_all || Q_stricmp(name, "weapons") == 0)
00313 {
00314 ent->client->ps.stats[STAT_WEAPONS] = (1 << (LAST_USEABLE_WEAPON+1)) - ( 1 << WP_NONE );
00315 if (!give_all)
00316 return;
00317 }
00318
00319 if ( !give_all && Q_stricmp(name, "weaponnum") == 0 )
00320 {
00321 trap_Argv( 2+baseArg, arg, sizeof( arg ) );
00322 ent->client->ps.stats[STAT_WEAPONS] |= (1 << atoi(arg));
00323 return;
00324 }
00325
00326 if (give_all || Q_stricmp(name, "ammo") == 0)
00327 {
00328 int num = 999;
00329 if (trap_Argc() == 3+baseArg) {
00330 trap_Argv( 2+baseArg, arg, sizeof( arg ) );
00331 num = atoi(arg);
00332 }
00333 for ( i = 0 ; i < MAX_WEAPONS ; i++ ) {
00334 ent->client->ps.ammo[i] = num;
00335 }
00336 if (!give_all)
00337 return;
00338 }
00339
00340 if (give_all || Q_stricmp(name, "armor") == 0)
00341 {
00342 if (trap_Argc() == 3+baseArg) {
00343 trap_Argv( 2+baseArg, arg, sizeof( arg ) );
00344 ent->client->ps.stats[STAT_ARMOR] = atoi(arg);
00345 } else {
00346 ent->client->ps.stats[STAT_ARMOR] = ent->client->ps.stats[STAT_MAX_HEALTH];
00347 }
00348
00349 if (!give_all)
00350 return;
00351 }
00352
00353 if (Q_stricmp(name, "excellent") == 0) {
00354 ent->client->ps.persistant[PERS_EXCELLENT_COUNT]++;
00355 return;
00356 }
00357 if (Q_stricmp(name, "impressive") == 0) {
00358 ent->client->ps.persistant[PERS_IMPRESSIVE_COUNT]++;
00359 return;
00360 }
00361 if (Q_stricmp(name, "gauntletaward") == 0) {
00362 ent->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT]++;
00363 return;
00364 }
00365 if (Q_stricmp(name, "defend") == 0) {
00366 ent->client->ps.persistant[PERS_DEFEND_COUNT]++;
00367 return;
00368 }
00369 if (Q_stricmp(name, "assist") == 0) {
00370 ent->client->ps.persistant[PERS_ASSIST_COUNT]++;
00371 return;
00372 }
00373
00374
00375 if ( !give_all ) {
00376 it = BG_FindItem (name);
00377 if (!it) {
00378 return;
00379 }
00380
00381 it_ent = G_Spawn();
00382 VectorCopy( ent->r.currentOrigin, it_ent->s.origin );
00383 it_ent->classname = it->classname;
00384 G_SpawnItem (it_ent, it);
00385 FinishSpawningItem(it_ent );
00386 memset( &trace, 0, sizeof( trace ) );
00387 Touch_Item (it_ent, ent, &trace);
00388 if (it_ent->inuse) {
00389 G_FreeEntity( it_ent );
00390 }
00391 }
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 void Cmd_God_f (gentity_t *ent)
00404 {
00405 char *msg;
00406
00407 if ( !CheatsOk( ent ) ) {
00408 return;
00409 }
00410
00411 ent->flags ^= FL_GODMODE;
00412 if (!(ent->flags & FL_GODMODE) )
00413 msg = "godmode OFF\n";
00414 else
00415 msg = "godmode ON\n";
00416
00417 trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 void Cmd_Notarget_f( gentity_t *ent ) {
00431 char *msg;
00432
00433 if ( !CheatsOk( ent ) ) {
00434 return;
00435 }
00436
00437 ent->flags ^= FL_NOTARGET;
00438 if (!(ent->flags & FL_NOTARGET) )
00439 msg = "notarget OFF\n";
00440 else
00441 msg = "notarget ON\n";
00442
00443 trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 void Cmd_Noclip_f( gentity_t *ent ) {
00455 char *msg;
00456
00457 if ( !CheatsOk( ent ) ) {
00458 return;
00459 }
00460
00461 if ( ent->client->noclip ) {
00462 msg = "noclip OFF\n";
00463 } else {
00464 msg = "noclip ON\n";
00465 }
00466 ent->client->noclip = !ent->client->noclip;
00467
00468 trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 void Cmd_LevelShot_f( gentity_t *ent ) {
00483 if ( !CheatsOk( ent ) ) {
00484 return;
00485 }
00486
00487
00488 if ( g_gametype.integer != 0 ) {
00489 trap_SendServerCommand( ent-g_entities,
00490 "print \"Must be in g_gametype 0 for levelshot\n\"" );
00491 return;
00492 }
00493
00494 BeginIntermission();
00495 trap_SendServerCommand( ent-g_entities, "clientLevelShot" );
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 void Cmd_TeamTask_f( gentity_t *ent ) {
00507 char userinfo[MAX_INFO_STRING];
00508 char arg[MAX_TOKEN_CHARS];
00509 int task;
00510 int client = ent->client - level.clients;
00511
00512 if ( trap_Argc() != 2 ) {
00513 return;
00514 }
00515 trap_Argv( 1, arg, sizeof( arg ) );
00516 task = atoi( arg );
00517
00518 trap_GetUserinfo(client, userinfo, sizeof(userinfo));
00519 Info_SetValueForKey(userinfo, "teamtask", va("%d", task));
00520 trap_SetUserinfo(client, userinfo);
00521 ClientUserinfoChanged(client);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531 void Cmd_Kill_f( gentity_t *ent ) {
00532 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
00533 return;
00534 }
00535 if (ent->health <= 0) {
00536 return;
00537 }
00538
00539 if ((g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) &&
00540 level.numPlayingClients > 1 && !level.warmupTime)
00541 {
00542 if (!g_allowDuelSuicide.integer)
00543 {
00544 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "ATTEMPTDUELKILL")) );
00545 return;
00546 }
00547 }
00548
00549 ent->flags &= ~FL_GODMODE;
00550 ent->client->ps.stats[STAT_HEALTH] = ent->health = -999;
00551 player_die (ent, ent, ent, 100000, MOD_SUICIDE);
00552 }
00553
00554 gentity_t *G_GetDuelWinner(gclient_t *client)
00555 {
00556 gclient_t *wCl;
00557 int i;
00558
00559 for ( i = 0 ; i < level.maxclients ; i++ ) {
00560 wCl = &level.clients[i];
00561
00562 if (wCl && wCl != client &&
00563 wCl->pers.connected == CON_CONNECTED && wCl->sess.sessionTeam != TEAM_SPECTATOR)
00564 {
00565 return &g_entities[wCl->ps.clientNum];
00566 }
00567 }
00568
00569 return NULL;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579 void BroadcastTeamChange( gclient_t *client, int oldTeam )
00580 {
00581 client->ps.fd.forceDoInit = 1;
00582
00583 if (g_gametype.integer == GT_SIEGE)
00584 {
00585 return;
00586 }
00587
00588 if ( client->sess.sessionTeam == TEAM_RED ) {
00589 trap_SendServerCommand( -1, va("cp \"%s" S_COLOR_WHITE " %s\n\"",
00590 client->pers.netname, G_GetStringEdString("MP_SVGAME", "JOINEDTHEREDTEAM")) );
00591 } else if ( client->sess.sessionTeam == TEAM_BLUE ) {
00592 trap_SendServerCommand( -1, va("cp \"%s" S_COLOR_WHITE " %s\n\"",
00593 client->pers.netname, G_GetStringEdString("MP_SVGAME", "JOINEDTHEBLUETEAM")));
00594 } else if ( client->sess.sessionTeam == TEAM_SPECTATOR && oldTeam != TEAM_SPECTATOR ) {
00595 trap_SendServerCommand( -1, va("cp \"%s" S_COLOR_WHITE " %s\n\"",
00596 client->pers.netname, G_GetStringEdString("MP_SVGAME", "JOINEDTHESPECTATORS")));
00597 } else if ( client->sess.sessionTeam == TEAM_FREE ) {
00598 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
00599 {
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 }
00616 else
00617 {
00618 trap_SendServerCommand( -1, va("cp \"%s" S_COLOR_WHITE " %s\n\"",
00619 client->pers.netname, G_GetStringEdString("MP_SVGAME", "JOINEDTHEBATTLE")));
00620 }
00621 }
00622
00623 G_LogPrintf ( "setteam: %i %s %s\n",
00624 client - &level.clients[0],
00625 TeamName ( oldTeam ),
00626 TeamName ( client->sess.sessionTeam ) );
00627 }
00628
00629 qboolean G_PowerDuelCheckFail(gentity_t *ent)
00630 {
00631 int loners = 0;
00632 int doubles = 0;
00633
00634 if (!ent->client || ent->client->sess.duelTeam == DUELTEAM_FREE)
00635 {
00636 return qtrue;
00637 }
00638
00639 G_PowerDuelCount(&loners, &doubles, qfalse);
00640
00641 if (ent->client->sess.duelTeam == DUELTEAM_LONE && loners >= 1)
00642 {
00643 return qtrue;
00644 }
00645
00646 if (ent->client->sess.duelTeam == DUELTEAM_DOUBLE && doubles >= 2)
00647 {
00648 return qtrue;
00649 }
00650
00651 return qfalse;
00652 }
00653
00654
00655
00656
00657
00658
00659 qboolean g_dontPenalizeTeam = qfalse;
00660 qboolean g_preventTeamBegin = qfalse;
00661 void SetTeam( gentity_t *ent, char *s ) {
00662 int team, oldTeam;
00663 gclient_t *client;
00664 int clientNum;
00665 spectatorState_t specState;
00666 int specClient;
00667 int teamLeader;
00668
00669
00670
00671
00672 client = ent->client;
00673
00674 clientNum = client - level.clients;
00675 specClient = 0;
00676 specState = SPECTATOR_NOT;
00677 if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) {
00678 team = TEAM_SPECTATOR;
00679 specState = SPECTATOR_SCOREBOARD;
00680 } else if ( !Q_stricmp( s, "follow1" ) ) {
00681 team = TEAM_SPECTATOR;
00682 specState = SPECTATOR_FOLLOW;
00683 specClient = -1;
00684 } else if ( !Q_stricmp( s, "follow2" ) ) {
00685 team = TEAM_SPECTATOR;
00686 specState = SPECTATOR_FOLLOW;
00687 specClient = -2;
00688 } else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) {
00689 team = TEAM_SPECTATOR;
00690 specState = SPECTATOR_FREE;
00691 } else if ( g_gametype.integer >= GT_TEAM ) {
00692
00693 specState = SPECTATOR_NOT;
00694 if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
00695 team = TEAM_RED;
00696 } else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
00697 team = TEAM_BLUE;
00698 } else {
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 team = PickTeam( clientNum );
00717
00718 }
00719
00720 if ( g_teamForceBalance.integer && !g_trueJedi.integer ) {
00721 int counts[TEAM_NUM_TEAMS];
00722
00723 counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE );
00724 counts[TEAM_RED] = TeamCount( ent->client->ps.clientNum, TEAM_RED );
00725
00726
00727 if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) {
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 {
00738 trap_SendServerCommand( ent->client->ps.clientNum,
00739 va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "TOOMANYRED")) );
00740 }
00741 return;
00742 }
00743 if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) {
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 {
00754 trap_SendServerCommand( ent->client->ps.clientNum,
00755 va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "TOOMANYBLUE")) );
00756 }
00757 return;
00758 }
00759
00760
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 } else {
00781
00782 team = TEAM_FREE;
00783 }
00784
00785 if (g_gametype.integer == GT_SIEGE)
00786 {
00787 if (client->tempSpectate >= level.time &&
00788 team == TEAM_SPECTATOR)
00789 {
00790 return;
00791 }
00792
00793 client->sess.siegeDesiredTeam = team;
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 if (client->sess.sessionTeam != TEAM_SPECTATOR &&
00806 team != TEAM_SPECTATOR)
00807 {
00808
00809 qboolean doBegin;
00810 if (ent->client->tempSpectate >= level.time)
00811 {
00812 doBegin = qfalse;
00813 }
00814 else
00815 {
00816 doBegin = qtrue;
00817 }
00818
00819 if (doBegin)
00820 {
00821
00822 if (ent->health > 0)
00823 {
00824 ent->flags &= ~FL_GODMODE;
00825 ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
00826 player_die( ent, ent, ent, 100000, MOD_TEAM_CHANGE );
00827 }
00828 }
00829
00830 if (ent->client->sess.sessionTeam != ent->client->sess.siegeDesiredTeam)
00831 {
00832 SetTeamQuick(ent, ent->client->sess.siegeDesiredTeam, qfalse);
00833 }
00834
00835 return;
00836 }
00837 }
00838
00839
00840 if ( (g_gametype.integer == GT_DUEL)
00841 && level.numNonSpectatorClients >= 2 )
00842 {
00843 team = TEAM_SPECTATOR;
00844 }
00845 else if ( (g_gametype.integer == GT_POWERDUEL)
00846 && (level.numPlayingClients >= 3 || G_PowerDuelCheckFail(ent)) )
00847 {
00848 team = TEAM_SPECTATOR;
00849 }
00850 else if ( g_maxGameClients.integer > 0 &&
00851 level.numNonSpectatorClients >= g_maxGameClients.integer )
00852 {
00853 team = TEAM_SPECTATOR;
00854 }
00855
00856
00857
00858
00859 oldTeam = client->sess.sessionTeam;
00860 if ( team == oldTeam && team != TEAM_SPECTATOR ) {
00861 return;
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 if ( client->ps.stats[STAT_HEALTH] <= 0 && client->sess.sessionTeam != TEAM_SPECTATOR ) {
00876 MaintainBodyQueue(ent);
00877 }
00878
00879
00880 client->pers.teamState.state = TEAM_BEGIN;
00881 if ( oldTeam != TEAM_SPECTATOR ) {
00882
00883 ent->flags &= ~FL_GODMODE;
00884 ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
00885 g_dontPenalizeTeam = qtrue;
00886 player_die (ent, ent, ent, 100000, MOD_SUICIDE);
00887 g_dontPenalizeTeam = qfalse;
00888
00889 }
00890
00891 if ( team == TEAM_SPECTATOR ) {
00892 if ( (g_gametype.integer != GT_DUEL) || (oldTeam != TEAM_SPECTATOR) ) {
00893 client->sess.spectatorTime = level.time;
00894 }
00895 }
00896
00897 client->sess.sessionTeam = team;
00898 client->sess.spectatorState = specState;
00899 client->sess.spectatorClient = specClient;
00900
00901 client->sess.teamLeader = qfalse;
00902 if ( team == TEAM_RED || team == TEAM_BLUE ) {
00903 teamLeader = TeamLeader( team );
00904
00905 if ( teamLeader == -1 || ( !(g_entities[clientNum].r.svFlags & SVF_BOT) && (g_entities[teamLeader].r.svFlags & SVF_BOT) ) ) {
00906
00907 }
00908 }
00909
00910 if ( oldTeam == TEAM_RED || oldTeam == TEAM_BLUE ) {
00911 CheckTeamLeader( oldTeam );
00912 }
00913
00914 BroadcastTeamChange( client, oldTeam );
00915
00916
00917
00918 if (oldTeam != TEAM_SPECTATOR)
00919 {
00920 gentity_t *tent = G_TempEntity( client->ps.origin, EV_PLAYER_TELEPORT_OUT );
00921 tent->s.clientNum = clientNum;
00922 }
00923
00924
00925 ClientUserinfoChanged( clientNum );
00926
00927 if (!g_preventTeamBegin)
00928 {
00929 ClientBegin( clientNum, qfalse );
00930 }
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 void StopFollowing( gentity_t *ent ) {
00942 ent->client->ps.persistant[ PERS_TEAM ] = TEAM_SPECTATOR;
00943 ent->client->sess.sessionTeam = TEAM_SPECTATOR;
00944 ent->client->sess.spectatorState = SPECTATOR_FREE;
00945 ent->client->ps.pm_flags &= ~PMF_FOLLOW;
00946 ent->r.svFlags &= ~SVF_BOT;
00947 ent->client->ps.clientNum = ent - g_entities;
00948 ent->client->ps.weapon = WP_NONE;
00949 ent->client->ps.m_iVehicleNum = 0;
00950 ent->client->ps.viewangles[ROLL] = 0.0f;
00951 ent->client->ps.forceHandExtend = HANDEXTEND_NONE;
00952 ent->client->ps.forceHandExtendTime = 0;
00953 ent->client->ps.zoomMode = 0;
00954 ent->client->ps.zoomLocked = 0;
00955 ent->client->ps.zoomLockTime = 0;
00956 ent->client->ps.legsAnim = 0;
00957 ent->client->ps.legsTimer = 0;
00958 ent->client->ps.torsoAnim = 0;
00959 ent->client->ps.torsoTimer = 0;
00960 }
00961
00962
00963
00964
00965
00966
00967 void Cmd_Team_f( gentity_t *ent ) {
00968 int oldTeam;
00969 char s[MAX_TOKEN_CHARS];
00970
00971 if ( trap_Argc() != 2 ) {
00972 oldTeam = ent->client->sess.sessionTeam;
00973 switch ( oldTeam ) {
00974 case TEAM_BLUE:
00975 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PRINTBLUETEAM")) );
00976 break;
00977 case TEAM_RED:
00978 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PRINTREDTEAM")) );
00979 break;
00980 case TEAM_FREE:
00981 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PRINTFREETEAM")) );
00982 break;
00983 case TEAM_SPECTATOR:
00984 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PRINTSPECTEAM")) );
00985 break;
00986 }
00987 return;
00988 }
00989
00990 if ( ent->client->switchTeamTime > level.time ) {
00991 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOSWITCH")) );
00992 return;
00993 }
00994
00995 if (gEscaping)
00996 {
00997 return;
00998 }
00999
01000
01001 if ( g_gametype.integer == GT_DUEL
01002 && ent->client->sess.sessionTeam == TEAM_FREE ) {
01003
01004 trap_SendServerCommand( ent-g_entities, "print \"Cannot switch teams in Duel\n\"" );
01005 return;
01006
01007
01008 }
01009
01010 if (g_gametype.integer == GT_POWERDUEL)
01011 {
01012 trap_SendServerCommand( ent-g_entities, "print \"Cannot switch teams in Power Duel\n\"" );
01013 return;
01014 }
01015
01016 trap_Argv( 1, s, sizeof( s ) );
01017
01018 SetTeam( ent, s );
01019
01020 ent->client->switchTeamTime = level.time + 5000;
01021 }
01022
01023
01024
01025
01026
01027
01028 void Cmd_DuelTeam_f(gentity_t *ent)
01029 {
01030 int oldTeam;
01031 char s[MAX_TOKEN_CHARS];
01032
01033 if (g_gametype.integer != GT_POWERDUEL)
01034 {
01035 return;
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 if ( trap_Argc() != 2 )
01047 {
01048 oldTeam = ent->client->sess.duelTeam;
01049 switch ( oldTeam )
01050 {
01051 case DUELTEAM_FREE:
01052 trap_SendServerCommand( ent-g_entities, va("print \"None\n\"") );
01053 break;
01054 case DUELTEAM_LONE:
01055 trap_SendServerCommand( ent-g_entities, va("print \"Single\n\"") );
01056 break;
01057 case DUELTEAM_DOUBLE:
01058 trap_SendServerCommand( ent-g_entities, va("print \"Double\n\"") );
01059 break;
01060 default:
01061 break;
01062 }
01063 return;
01064 }
01065
01066 if ( ent->client->switchDuelTeamTime > level.time )
01067 {
01068 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOSWITCH")) );
01069 return;
01070 }
01071
01072 trap_Argv( 1, s, sizeof( s ) );
01073
01074 oldTeam = ent->client->sess.duelTeam;
01075
01076 if (!Q_stricmp(s, "free"))
01077 {
01078 ent->client->sess.duelTeam = DUELTEAM_FREE;
01079 }
01080 else if (!Q_stricmp(s, "single"))
01081 {
01082 ent->client->sess.duelTeam = DUELTEAM_LONE;
01083 }
01084 else if (!Q_stricmp(s, "double"))
01085 {
01086 ent->client->sess.duelTeam = DUELTEAM_DOUBLE;
01087 }
01088 else
01089 {
01090 trap_SendServerCommand( ent-g_entities, va("print \"'%s' not a valid duel team.\n\"", s) );
01091 }
01092
01093 if (oldTeam == ent->client->sess.duelTeam)
01094 {
01095 return;
01096 }
01097
01098 if (ent->client->sess.sessionTeam != TEAM_SPECTATOR)
01099 {
01100 int curTeam = ent->client->sess.duelTeam;
01101 ent->client->sess.duelTeam = oldTeam;
01102 G_Damage(ent, ent, ent, NULL, ent->client->ps.origin, 99999, DAMAGE_NO_PROTECTION, MOD_SUICIDE);
01103 ent->client->sess.duelTeam = curTeam;
01104 }
01105
01106 ent->client->sess.wins = 0;
01107 ent->client->sess.losses = 0;
01108
01109
01110 ClientUserinfoChanged( ent->s.number );
01111
01112 ent->client->switchDuelTeamTime = level.time + 5000;
01113 }
01114
01115 int G_TeamForSiegeClass(const char *clName)
01116 {
01117 int i = 0;
01118 int team = SIEGETEAM_TEAM1;
01119 siegeTeam_t *stm = BG_SiegeFindThemeForTeam(team);
01120 siegeClass_t *scl;
01121
01122 if (!stm)
01123 {
01124 return 0;
01125 }
01126
01127 while (team <= SIEGETEAM_TEAM2)
01128 {
01129 scl = stm->classes[i];
01130
01131 if (scl && scl->name[0])
01132 {
01133 if (!Q_stricmp(clName, scl->name))
01134 {
01135 return team;
01136 }
01137 }
01138
01139 i++;
01140 if (i >= MAX_SIEGE_CLASSES || i >= stm->numClasses)
01141 {
01142 if (team == SIEGETEAM_TEAM2)
01143 {
01144 break;
01145 }
01146 team = SIEGETEAM_TEAM2;
01147 stm = BG_SiegeFindThemeForTeam(team);
01148 i = 0;
01149 }
01150 }
01151
01152 return 0;
01153 }
01154
01155
01156
01157
01158
01159
01160 void Cmd_SiegeClass_f( gentity_t *ent )
01161 {
01162 char className[64];
01163 int team = 0;
01164 int preScore;
01165 qboolean startedAsSpec = qfalse;
01166
01167 if (g_gametype.integer != GT_SIEGE)
01168 {
01169 return;
01170 }
01171
01172 if (!ent->client)
01173 {
01174 return;
01175 }
01176
01177 if (trap_Argc() < 1)
01178 {
01179 return;
01180 }
01181
01182 if ( ent->client->switchClassTime > level.time )
01183 {
01184 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOCLASSSWITCH")) );
01185 return;
01186 }
01187
01188 if (ent->client->sess.sessionTeam == TEAM_SPECTATOR)
01189 {
01190 startedAsSpec = qtrue;
01191 }
01192
01193 trap_Argv( 1, className, sizeof( className ) );
01194
01195 team = G_TeamForSiegeClass(className);
01196
01197 if (!team)
01198 {
01199 return;
01200 }
01201
01202 if (ent->client->sess.sessionTeam != team)
01203 {
01204 g_preventTeamBegin = qtrue;
01205 if (team == TEAM_RED)
01206 {
01207 SetTeam(ent, "red");
01208 }
01209 else if (team == TEAM_BLUE)
01210 {
01211 SetTeam(ent, "blue");
01212 }
01213 g_preventTeamBegin = qfalse;
01214
01215 if (ent->client->sess.sessionTeam != team)
01216 {
01217 if (ent->client->sess.sessionTeam != TEAM_SPECTATOR ||
01218 ent->client->sess.siegeDesiredTeam != team)
01219 {
01220 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOCLASSTEAM")) );
01221 return;
01222 }
01223 }
01224 }
01225
01226
01227 preScore = ent->client->ps.persistant[PERS_SCORE];
01228
01229
01230 BG_SiegeCheckClassLegality(team, className);
01231
01232
01233 strcpy(ent->client->sess.siegeClass, className);
01234
01235
01236 ClientUserinfoChanged( ent->s.number );
01237
01238 if (ent->client->tempSpectate < level.time)
01239 {
01240
01241 if (ent->health > 0 && !startedAsSpec)
01242 {
01243 ent->flags &= ~FL_GODMODE;
01244 ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
01245 player_die (ent, ent, ent, 100000, MOD_SUICIDE);
01246 }
01247
01248 if (ent->client->sess.sessionTeam == TEAM_SPECTATOR || startedAsSpec)
01249 {
01250 ClientBegin( ent->s.number, qfalse );
01251 }
01252 }
01253
01254 ent->client->ps.persistant[