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[PERS_SCORE] = preScore;
01255
01256 ent->client->switchClassTime = level.time + 5000;
01257 }
01258
01259
01260
01261
01262
01263
01264 void Cmd_ForceChanged_f( gentity_t *ent )
01265 {
01266 char fpChStr[1024];
01267 const char *buf;
01268
01269 if (ent->client->sess.sessionTeam == TEAM_SPECTATOR)
01270 {
01271
01272
01273 WP_InitForcePowers( ent );
01274 goto argCheck;
01275 }
01276
01277 buf = G_GetStringEdString("MP_SVGAME", "FORCEPOWERCHANGED");
01278
01279 strcpy(fpChStr, buf);
01280
01281 trap_SendServerCommand( ent-g_entities, va("print \"%s%s\n\n\"", S_COLOR_GREEN, fpChStr) );
01282
01283 ent->client->ps.fd.forceDoInit = 1;
01284 argCheck:
01285 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
01286 {
01287 return;
01288 }
01289
01290 if (trap_Argc() > 1)
01291 {
01292 char arg[MAX_TOKEN_CHARS];
01293
01294 trap_Argv( 1, arg, sizeof( arg ) );
01295
01296 if (arg && arg[0])
01297 {
01298 Cmd_Team_f(ent);
01299 }
01300 }
01301 }
01302
01303 extern qboolean WP_SaberStyleValidForSaber( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int saberAnimLevel );
01304 extern qboolean WP_UseFirstValidSaberStyle( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int *saberAnimLevel );
01305 qboolean G_SetSaber(gentity_t *ent, int saberNum, char *saberName, qboolean siegeOverride)
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 {
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 {
01331 strcpy(truncSaberName, "Kyle");
01332 }
01333
01334
01335
01336 WP_SetSaber(ent->s.number, ent->client->saber, saberNum, truncSaberName);
01337
01338 if (!ent->client->saber[0].model[0])
01339 {
01340 assert(0);
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 }
01365
01366
01367
01368
01369
01370
01371 void Cmd_Follow_f( gentity_t *ent ) {
01372 int i;
01373 char arg[MAX_TOKEN_CHARS];
01374
01375 if ( trap_Argc() != 2 ) {
01376 if ( ent->client->sess.spectatorState == SPECTATOR_FOLLOW ) {
01377 StopFollowing( ent );
01378 }
01379 return;
01380 }
01381
01382 trap_Argv( 1, arg, sizeof( arg ) );
01383 i = ClientNumberFromString( ent, arg );
01384 if ( i == -1 ) {
01385 return;
01386 }
01387
01388
01389 if ( &level.clients[ i ] == ent->client ) {
01390 return;
01391 }
01392
01393
01394 if ( level.clients[ i ].sess.sessionTeam == TEAM_SPECTATOR ) {
01395 return;
01396 }
01397
01398
01399 if ( (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
01400 && ent->client->sess.sessionTeam == TEAM_FREE ) {
01401
01402 ent->client->sess.losses++;
01403 }
01404
01405
01406 if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
01407 SetTeam( ent, "spectator" );
01408 }
01409
01410 ent->client->sess.spectatorState = SPECTATOR_FOLLOW;
01411 ent->client->sess.spectatorClient = i;
01412 }
01413
01414
01415
01416
01417
01418
01419 void Cmd_FollowCycle_f( gentity_t *ent, int dir ) {
01420 int clientnum;
01421 int original;
01422
01423
01424 if ( (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
01425 && ent->client->sess.sessionTeam == TEAM_FREE ) {\
01426
01427 ent->client->sess.losses++;
01428 }
01429
01430 if ( ent->client->sess.spectatorState == SPECTATOR_NOT ) {
01431 SetTeam( ent, "spectator" );
01432 }
01433
01434 if ( dir != 1 && dir != -1 ) {
01435 G_Error( "Cmd_FollowCycle_f: bad dir %i", dir );
01436 }
01437
01438 clientnum = ent->client->sess.spectatorClient;
01439 original = clientnum;
01440 do {
01441 clientnum += dir;
01442 if ( clientnum >= level.maxclients ) {
01443 clientnum = 0;
01444 }
01445 if ( clientnum < 0 ) {
01446 clientnum = level.maxclients - 1;
01447 }
01448
01449
01450 if ( level.clients[ clientnum ].pers.connected != CON_CONNECTED ) {
01451 continue;
01452 }
01453
01454
01455 if ( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) {
01456 continue;
01457 }
01458
01459
01460 ent->client->sess.spectatorClient = clientnum;
01461 ent->client->sess.spectatorState = SPECTATOR_FOLLOW;
01462 return;
01463 } while ( clientnum != original );
01464
01465
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message, char *locMsg )
01476 {
01477 if (!other) {
01478 return;
01479 }
01480 if (!other->inuse) {
01481 return;
01482 }
01483 if (!other->client) {
01484 return;
01485 }
01486 if ( other->client->pers.connected != CON_CONNECTED ) {
01487 return;
01488 }
01489 if ( mode == SAY_TEAM && !OnSameTeam(ent, other) ) {
01490 return;
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 if (g_gametype.integer == GT_SIEGE &&
01504 ent->client && (ent->client->tempSpectate >= level.time || ent->client->sess.sessionTeam == TEAM_SPECTATOR) &&
01505 other->client->sess.sessionTeam != TEAM_SPECTATOR &&
01506 other->client->tempSpectate < level.time)
01507 {
01508 return;
01509 }
01510
01511 if (locMsg)
01512 {
01513 trap_SendServerCommand( other-g_entities, va("%s \"%s\" \"%s\" \"%c\" \"%s\"",
01514 mode == SAY_TEAM ? "ltchat" : "lchat",
01515 name, locMsg, color, message));
01516 }
01517 else
01518 {
01519 trap_SendServerCommand( other-g_entities, va("%s \"%s%c%c%s\"",
01520 mode == SAY_TEAM ? "tchat" : "chat",
01521 name, Q_COLOR_ESCAPE, color, message));
01522 }
01523 }
01524
01525 #define EC "\x19"
01526
01527 void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) {
01528 int j;
01529 gentity_t *other;
01530 int color;
01531 char name[64];
01532
01533 char text[MAX_SAY_TEXT];
01534 char location[64];
01535 char *locMsg = NULL;
01536
01537 if ( g_gametype.integer < GT_TEAM && mode == SAY_TEAM ) {
01538 mode = SAY_ALL;
01539 }
01540
01541 switch ( mode ) {
01542 default:
01543 case SAY_ALL:
01544 G_LogPrintf( "say: %s: %s\n", ent->client->pers.netname, chatText );
01545 Com_sprintf (name, sizeof(name), "%s%c%c"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );
01546 color = COLOR_GREEN;
01547 break;
01548 case SAY_TEAM:
01549 G_LogPrintf( "sayteam: %s: %s\n", ent->client->pers.netname, chatText );
01550 if (Team_GetLocationMsg(ent, location, sizeof(location)))
01551 {
01552 Com_sprintf (name, sizeof(name), EC"(%s%c%c"EC")"EC": ",
01553 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );
01554 locMsg = location;
01555 }
01556 else
01557 {
01558 Com_sprintf (name, sizeof(name), EC"(%s%c%c"EC")"EC": ",
01559 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );
01560 }
01561 color = COLOR_CYAN;
01562 break;
01563 case SAY_TELL:
01564 if (target && g_gametype.integer >= GT_TEAM &&
01565 target->client->sess.sessionTeam == ent->client->sess.sessionTeam &&
01566 Team_GetLocationMsg(ent, location, sizeof(location)))
01567 {
01568 Com_sprintf (name, sizeof(name), EC"[%s%c%c"EC"]"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );
01569 locMsg = location;
01570 }
01571 else
01572 {
01573 Com_sprintf (name, sizeof(name), EC"[%s%c%c"EC"]"EC": ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE );
01574 }
01575 color = COLOR_MAGENTA;
01576 break;
01577 }
01578
01579 Q_strncpyz( text, chatText, sizeof(text) );
01580
01581 if ( target ) {
01582 G_SayTo( ent, target, mode, color, name, text, locMsg );
01583 return;
01584 }
01585
01586
01587 if ( g_dedicated.integer ) {
01588 G_Printf( "%s%s\n", name, text);
01589 }
01590
01591
01592 for (j = 0; j < level.maxclients; j++) {
01593 other = &g_entities[j];
01594 G_SayTo( ent, other, mode, color, name, text, locMsg );
01595 }
01596 }
01597
01598
01599
01600
01601
01602
01603
01604 static void Cmd_Say_f( gentity_t *ent, int mode, qboolean arg0 ) {
01605 char *p;
01606
01607 if ( trap_Argc () < 2 && !arg0 ) {
01608 return;
01609 }
01610
01611 if (arg0)
01612 {
01613 p = ConcatArgs( 0 );
01614 }
01615 else
01616 {
01617 p = ConcatArgs( 1 );
01618 }
01619
01620 G_Say( ent, NULL, mode, p );
01621 }
01622
01623
01624
01625
01626
01627
01628 static void Cmd_Tell_f( gentity_t *ent ) {
01629 int targetNum;
01630 gentity_t *target;
01631 char *p;
01632 char arg[MAX_TOKEN_CHARS];
01633
01634 if ( trap_Argc () < 2 ) {
01635 return;
01636 }
01637
01638 trap_Argv( 1, arg, sizeof( arg ) );
01639 targetNum = atoi( arg );
01640 if ( targetNum < 0 || targetNum >= level.maxclients ) {
01641 return;
01642 }
01643
01644 target = &g_entities[targetNum];
01645 if ( !target || !target->inuse || !target->client ) {
01646 return;
01647 }
01648
01649 p = ConcatArgs( 2 );
01650
01651 G_LogPrintf( "tell: %s to %s: %s\n", ent->client->pers.netname, target->client->pers.netname, p );
01652 G_Say( ent, target, SAY_TELL, p );
01653
01654
01655 if ( ent != target && !(ent->r.svFlags & SVF_BOT)) {
01656 G_Say( ent, ent, SAY_TELL, p );
01657 }
01658 }
01659
01660
01661 static void Cmd_VoiceCommand_f(gentity_t *ent)
01662 {
01663 gentity_t *te;
01664 char arg[MAX_TOKEN_CHARS];
01665 char *s;
01666 int i = 0;
01667
01668 if (g_gametype.integer < GT_TEAM)
01669 {
01670 return;
01671 }
01672
01673 if (trap_Argc() < 2)
01674 {
01675 return;
01676 }
01677
01678 if (ent->client->sess.sessionTeam == TEAM_SPECTATOR ||
01679 ent->client->tempSpectate >= level.time)
01680 {
01681 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOICECHATASSPEC")) );
01682 return;
01683 }
01684
01685 trap_Argv(1, arg, sizeof(arg));
01686
01687 if (arg[0] == '*')
01688 {
01689 return;
01690 }
01691
01692 s = va("*%s", arg);
01693
01694
01695
01696 while (i < MAX_CUSTOM_SIEGE_SOUNDS)
01697 {
01698 if (!bg_customSiegeSoundNames[i])
01699 {
01700 break;
01701 }
01702 if (!Q_stricmp(bg_customSiegeSoundNames[i], s))
01703 {
01704 break;
01705 }
01706 i++;
01707 }
01708
01709 if (i == MAX_CUSTOM_SIEGE_SOUNDS || !bg_customSiegeSoundNames[i])
01710 {
01711 return;
01712 }
01713
01714 te = G_TempEntity(vec3_origin, EV_VOICECMD_SOUND);
01715 te->s.groundEntityNum = ent->s.number;
01716 te->s.eventParm = G_SoundIndex((char *)bg_customSiegeSoundNames[i]);
01717 te->r.svFlags |= SVF_BROADCAST;
01718 }
01719
01720
01721 static char *gc_orders[] = {
01722 "hold your position",
01723 "hold this position",
01724 "come here",
01725 "cover me",
01726 "guard location",
01727 "search and destroy",
01728 "report"
01729 };
01730
01731 void Cmd_GameCommand_f( gentity_t *ent ) {
01732 int player;
01733 int order;
01734 char str[MAX_TOKEN_CHARS];
01735
01736 trap_Argv( 1, str, sizeof( str ) );
01737 player = atoi( str );
01738 trap_Argv( 2, str, sizeof( str ) );
01739 order = atoi( str );
01740
01741 if ( player < 0 || player >= MAX_CLIENTS ) {
01742 return;
01743 }
01744 if ( order < 0 || order > sizeof(gc_orders)/sizeof(char *) ) {
01745 return;
01746 }
01747 G_Say( ent, &g_entities[player], SAY_TELL, gc_orders[order] );
01748 G_Say( ent, ent, SAY_TELL, gc_orders[order] );
01749 }
01750
01751
01752
01753
01754
01755
01756 void Cmd_Where_f( gentity_t *ent ) {
01757 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", vtos( ent->s.origin ) ) );
01758 }
01759
01760 static const char *gameNames[] = {
01761 "Free For All",
01762 "Holocron FFA",
01763 "Jedi Master",
01764 "Duel",
01765 "Power Duel",
01766 "Single Player",
01767 "Team FFA",
01768 "Siege",
01769 "Capture the Flag",
01770 "Capture the Ysalamiri"
01771 };
01772
01773
01774
01775
01776
01777
01778
01779
01780 int G_ClientNumberFromName ( const char* name )
01781 {
01782 char s2[MAX_STRING_CHARS];
01783 char n2[MAX_STRING_CHARS];
01784 int i;
01785 gclient_t* cl;
01786
01787
01788 SanitizeString( (char*)name, s2 );
01789 for ( i=0, cl=level.clients ; i < level.numConnectedClients ; i++, cl++ )
01790 {
01791 SanitizeString( cl->pers.netname, n2 );
01792 if ( !strcmp( n2, s2 ) )
01793 {
01794 return i;
01795 }
01796 }
01797
01798 return -1;
01799 }
01800
01801
01802
01803
01804
01805
01806
01807
01808 void SanitizeString2( char *in, char *out )
01809 {
01810 int i = 0;
01811 int r = 0;
01812
01813 while (in[i])
01814 {
01815 if (i >= MAX_NAME_LENGTH-1)
01816 {
01817 break;
01818 }
01819
01820 if (in[i] == '^')
01821 {
01822 if (in[i+1] >= 48 &&
01823 in[i+1] <= 57)
01824 {
01825 i += 2;
01826 continue;
01827 }
01828 else
01829 {
01830 i++;
01831 continue;
01832 }
01833 }
01834
01835 if (in[i] < 32)
01836 {
01837 i++;
01838 continue;
01839 }
01840
01841 out[r] = in[i];
01842 r++;
01843 i++;
01844 }
01845 out[r] = 0;
01846 }
01847
01848
01849
01850
01851
01852
01853
01854
01855 int G_ClientNumberFromStrippedName ( const char* name )
01856 {
01857 char s2[MAX_STRING_CHARS];
01858 char n2[MAX_STRING_CHARS];
01859 int i;
01860 gclient_t* cl;
01861
01862
01863 SanitizeString2( (char*)name, s2 );
01864 for ( i=0, cl=level.clients ; i < level.numConnectedClients ; i++, cl++ )
01865 {
01866 SanitizeString2( cl->pers.netname, n2 );
01867 if ( !strcmp( n2, s2 ) )
01868 {
01869 return i;
01870 }
01871 }
01872
01873 return -1;
01874 }
01875
01876
01877
01878
01879
01880
01881 extern void SiegeClearSwitchData(void);
01882 const char *G_GetArenaInfoByMap( const char *map );
01883 void Cmd_CallVote_f( gentity_t *ent ) {
01884 int i;
01885 char arg1[MAX_STRING_TOKENS];
01886 char arg2[MAX_STRING_TOKENS];
01887
01888
01889 char* mapName = 0;
01890 const char* arenaInfo;
01891
01892 if ( !g_allowVote.integer ) {
01893 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTE")) );
01894 return;
01895 }
01896
01897 if ( level.voteTime || level.voteExecuteTime >= level.time ) {
01898 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "VOTEINPROGRESS")) );
01899 return;
01900 }
01901 if ( ent->client->pers.voteCount >= MAX_VOTE_COUNT ) {
01902 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "MAXVOTES")) );
01903 return;
01904 }
01905
01906 if (g_gametype.integer != GT_DUEL &&
01907 g_gametype.integer != GT_POWERDUEL)
01908 {
01909 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
01910 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOSPECVOTE")) );
01911 return;
01912 }
01913 }
01914
01915
01916 trap_Argv( 1, arg1, sizeof( arg1 ) );
01917 trap_Argv( 2, arg2, sizeof( arg2 ) );
01918
01919 if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) {
01920 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
01921 return;
01922 }
01923
01924 if ( !Q_stricmp( arg1, "map_restart" ) ) {
01925 } else if ( !Q_stricmp( arg1, "nextmap" ) ) {
01926 } else if ( !Q_stricmp( arg1, "map" ) ) {
01927 } else if ( !Q_stricmp( arg1, "g_gametype" ) ) {
01928 } else if ( !Q_stricmp( arg1, "kick" ) ) {
01929 } else if ( !Q_stricmp( arg1, "clientkick" ) ) {
01930 } else if ( !Q_stricmp( arg1, "g_doWarmup" ) ) {
01931 } else if ( !Q_stricmp( arg1, "timelimit" ) ) {
01932 } else if ( !Q_stricmp( arg1, "fraglimit" ) ) {
01933 } else {
01934 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
01935 trap_SendServerCommand( ent-g_entities, "print \"Vote commands are: map_restart, nextmap, map <mapname>, g_gametype <n>, kick <player>, clientkick <clientnum>, g_doWarmup, timelimit <time>, fraglimit <frags>.\n\"" );
01936 return;
01937 }
01938
01939
01940 if ( level.voteExecuteTime ) {
01941 level.voteExecuteTime = 0;
01942 trap_SendConsoleCommand( EXEC_APPEND, va("%s\n", level.voteString ) );
01943 }
01944
01945
01946 if ( !Q_stricmp( arg1, "g_gametype" ) )
01947 {
01948 i = atoi( arg2 );
01949 if( i == GT_SINGLE_PLAYER || i < GT_FFA || i >= GT_MAX_GAME_TYPE) {
01950 trap_SendServerCommand( ent-g_entities, "print \"Invalid gametype.\n\"" );
01951 return;
01952 }
01953
01954 level.votingGametype = qtrue;
01955 level.votingGametypeTo = i;
01956
01957 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %d", arg1, i );
01958 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s %s", arg1, gameNames[i] );
01959 }
01960 else if ( !Q_stricmp( arg1, "map" ) )
01961 {
01962
01963
01964 char s[MAX_STRING_CHARS];
01965
01966 if (!G_DoesMapSupportGametype(arg2, trap_Cvar_VariableIntegerValue("g_gametype")))
01967 {
01968
01969 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTE_MAPNOTSUPPORTEDBYGAME")) );
01970 return;
01971 }
01972
01973 trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
01974 if (*s) {
01975 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s; set nextmap \"%s\"", arg1, arg2, s );
01976 } else {
01977 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 );
01978 }
01979
01980 arenaInfo = G_GetArenaInfoByMap(arg2);
01981 if (arenaInfo)
01982 {
01983 mapName = Info_ValueForKey(arenaInfo, "longname");
01984 }
01985
01986 if (!mapName || !mapName[0])
01987 {
01988 mapName = "ERROR";
01989 }
01990
01991 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "map %s", mapName);
01992 }
01993 else if ( !Q_stricmp ( arg1, "clientkick" ) )
01994 {
01995 int n = atoi ( arg2 );
01996
01997 if ( n < 0 || n >= MAX_CLIENTS )
01998 {
01999 trap_SendServerCommand( ent-g_entities, va("print \"invalid client number %d.\n\"", n ) );
02000 return;
02001 }
02002
02003 if ( g_entities[n].client->pers.connected == CON_DISCONNECTED )
02004 {
02005 trap_SendServerCommand( ent-g_entities, va("print \"there is no client with the client number %d.\n\"", n ) );
02006 return;
02007 }
02008
02009 Com_sprintf ( level.voteString, sizeof(level.voteString ), "%s %s", arg1, arg2 );
02010 Com_sprintf ( level.voteDisplayString, sizeof(level.voteDisplayString), "kick %s", g_entities[n].client->pers.netname );
02011 }
02012 else if ( !Q_stricmp ( arg1, "kick" ) )
02013 {
02014 int clientid = G_ClientNumberFromName ( arg2 );
02015
02016 if ( clientid == -1 )
02017 {
02018 clientid = G_ClientNumberFromStrippedName(arg2);
02019
02020 if (clientid == -1)
02021 {
02022 trap_SendServerCommand( ent-g_entities, va("print \"there is no client named '%s' currently on the server.\n\"", arg2 ) );
02023 return;
02024 }
02025 }
02026
02027 Com_sprintf ( level.voteString, sizeof(level.voteString ), "clientkick %d", clientid );
02028 Com_sprintf ( level.voteDisplayString, sizeof(level.voteDisplayString), "kick %s", g_entities[clientid].client->pers.netname );
02029 }
02030 else if ( !Q_stricmp( arg1, "nextmap" ) )
02031 {
02032 char s[MAX_STRING_CHARS];
02033
02034 trap_Cvar_VariableStringBuffer( "nextmap", s, sizeof(s) );
02035 if (!*s) {
02036 trap_SendServerCommand( ent-g_entities, "print \"nextmap not set.\n\"" );
02037 return;
02038 }
02039 SiegeClearSwitchData();
02040 Com_sprintf( level.voteString, sizeof( level.voteString ), "vstr nextmap");
02041 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
02042 }
02043 else
02044 {
02045 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s \"%s\"", arg1, arg2 );
02046 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "%s", level.voteString );
02047 }
02048
02049 trap_SendServerCommand( -1, va("print \"%s^7 %s\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLCALLEDVOTE") ) );
02050
02051
02052 level.voteTime = level.time;
02053 level.voteYes = 1;
02054 level.voteNo = 0;
02055
02056 for ( i = 0 ; i < level.maxclients ; i++ ) {
02057 level.clients[i].mGameFlags &= ~PSG_VOTED;
02058 }
02059 ent->client->mGameFlags |= PSG_VOTED;
02060
02061 trap_SetConfigstring( CS_VOTE_TIME, va("%i", level.voteTime ) );
02062 trap_SetConfigstring( CS_VOTE_STRING, level.voteDisplayString );
02063 trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) );
02064 trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) );
02065 }
02066
02067
02068
02069
02070
02071
02072 void Cmd_Vote_f( gentity_t *ent ) {
02073 char msg[64];
02074
02075 if ( !level.voteTime ) {
02076 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTEINPROG")) );
02077 return;
02078 }
02079 if ( ent->client->mGameFlags & PSG_VOTED ) {
02080 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "VOTEALREADY")) );
02081 return;
02082 }
02083 if (g_gametype.integer != GT_DUEL &&
02084 g_gametype.integer != GT_POWERDUEL)
02085 {
02086 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
02087 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTEASSPEC")) );
02088 return;
02089 }
02090 }
02091
02092 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PLVOTECAST")) );
02093
02094 ent->client->mGameFlags |= PSG_VOTED;
02095
02096 trap_Argv( 1, msg, sizeof( msg ) );
02097
02098 if ( msg[0] == 'y' || msg[1] == 'Y' || msg[1] == '1' ) {
02099 level.voteYes++;
02100 trap_SetConfigstring( CS_VOTE_YES, va("%i", level.voteYes ) );
02101 } else {
02102 level.voteNo++;
02103 trap_SetConfigstring( CS_VOTE_NO, va("%i", level.voteNo ) );
02104 }
02105
02106
02107
02108 }
02109
02110
02111
02112
02113
02114
02115 void Cmd_CallTeamVote_f( gentity_t *ent ) {
02116 int i, team, cs_offset;
02117 char arg1[MAX_STRING_TOKENS];
02118 char arg2[MAX_STRING_TOKENS];
02119
02120 team = ent->client->sess.sessionTeam;
02121 if ( team == TEAM_RED )
02122 cs_offset = 0;
02123 else if ( team == TEAM_BLUE )
02124 cs_offset = 1;
02125 else
02126 return;
02127
02128 if ( !g_allowVote.integer ) {
02129 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTE")) );
02130 return;
02131 }
02132
02133 if ( level.teamVoteTime[cs_offset] ) {
02134 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "TEAMVOTEALREADY")) );
02135 return;
02136 }
02137 if ( ent->client->pers.teamVoteCount >= MAX_VOTE_COUNT ) {
02138 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "MAXTEAMVOTES")) );
02139 return;
02140 }
02141 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
02142 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOSPECVOTE")) );
02143 return;
02144 }
02145
02146
02147 trap_Argv( 1, arg1, sizeof( arg1 ) );
02148 arg2[0] = '\0';
02149 for ( i = 2; i < trap_Argc(); i++ ) {
02150 if (i > 2)
02151 strcat(arg2, " ");
02152 trap_Argv( i, &arg2[strlen(arg2)], sizeof( arg2 ) - strlen(arg2) );
02153 }
02154
02155 if( strchr( arg1, ';' ) || strchr( arg2, ';' ) ) {
02156 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
02157 return;
02158 }
02159
02160 if ( !Q_stricmp( arg1, "leader" ) ) {
02161 char netname[MAX_NETNAME], leader[MAX_NETNAME];
02162
02163 if ( !arg2[0] ) {
02164 i = ent->client->ps.clientNum;
02165 }
02166 else {
02167
02168 for (i = 0; i < 3; i++) {
02169 if ( !arg2[i] || arg2[i] < '0' || arg2[i] > '9' )
02170 break;
02171 }
02172 if ( i >= 3 || !arg2[i]) {
02173 i = atoi( arg2 );
02174 if ( i < 0 || i >= level.maxclients ) {
02175 trap_SendServerCommand( ent-g_entities, va("print \"Bad client slot: %i\n\"", i) );
02176 return;
02177 }
02178
02179 if ( !g_entities[i].inuse ) {
02180 trap_SendServerCommand( ent-g_entities, va("print \"Client %i is not active\n\"", i) );
02181 return;
02182 }
02183 }
02184 else {
02185 Q_strncpyz(leader, arg2, sizeof(leader));
02186 Q_CleanStr(leader);
02187 for ( i = 0 ; i < level.maxclients ; i++ ) {
02188 if ( level.clients[i].pers.connected == CON_DISCONNECTED )
02189 continue;
02190 if (level.clients[i].sess.sessionTeam != team)
02191 continue;
02192 Q_strncpyz(netname, level.clients[i].pers.netname, sizeof(netname));
02193 Q_CleanStr(netname);
02194 if ( !Q_stricmp(netname, leader) ) {
02195 break;
02196 }
02197 }
02198 if ( i >= level.maxclients ) {
02199 trap_SendServerCommand( ent-g_entities, va("print \"%s is not a valid player on your team.\n\"", arg2) );
02200 return;
02201 }
02202 }
02203 }
02204 Com_sprintf(arg2, sizeof(arg2), "%d", i);
02205 } else {
02206 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" );
02207 trap_SendServerCommand( ent-g_entities, "print \"Team vote commands are: leader <player>.\n\"" );
02208 return;
02209 }
02210
02211 Com_sprintf( level.teamVoteString[cs_offset], sizeof( level.teamVoteString[cs_offset] ), "%s %s", arg1, arg2 );
02212
02213 for ( i = 0 ; i < level.maxclients ; i++ ) {
02214 if ( level.clients[i].pers.connected == CON_DISCONNECTED )
02215 continue;
02216 if (level.clients[i].sess.sessionTeam == team)
02217 trap_SendServerCommand( i, va("print \"%s called a team vote.\n\"", ent->client->pers.netname ) );
02218 }
02219
02220
02221 level.teamVoteTime[cs_offset] = level.time;
02222 level.teamVoteYes[cs_offset] = 1;
02223 level.teamVoteNo[cs_offset] = 0;
02224
02225 for ( i = 0 ; i < level.maxclients ; i++ ) {
02226 if (level.clients[i].sess.sessionTeam == team)
02227 level.clients[i].mGameFlags &= ~PSG_TEAMVOTED;
02228 }
02229 ent->client->mGameFlags |= PSG_TEAMVOTED;
02230
02231 trap_SetConfigstring( CS_TEAMVOTE_TIME + cs_offset, va("%i", level.teamVoteTime[cs_offset] ) );
02232 trap_SetConfigstring( CS_TEAMVOTE_STRING + cs_offset, level.teamVoteString[cs_offset] );
02233 trap_SetConfigstring( CS_TEAMVOTE_YES + cs_offset, va("%i", level.teamVoteYes[cs_offset] ) );
02234 trap_SetConfigstring( CS_TEAMVOTE_NO + cs_offset, va("%i", level.teamVoteNo[cs_offset] ) );
02235 }
02236
02237
02238
02239
02240
02241
02242 void Cmd_TeamVote_f( gentity_t *ent ) {
02243 int team, cs_offset;
02244 char msg[64];
02245
02246 team = ent->client->sess.sessionTeam;
02247 if ( team == TEAM_RED )
02248 cs_offset = 0;
02249 else if ( team == TEAM_BLUE )
02250 cs_offset = 1;
02251 else
02252 return;
02253
02254 if ( !level.teamVoteTime[cs_offset] ) {
02255 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOTEAMVOTEINPROG")) );
02256 return;
02257 }
02258 if ( ent->client->mGameFlags & PSG_TEAMVOTED ) {
02259 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "TEAMVOTEALREADYCAST")) );
02260 return;
02261 }
02262 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
02263 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOVOTEASSPEC")) );
02264 return;
02265 }
02266
02267 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PLTEAMVOTECAST")) );
02268
02269 ent->client->mGameFlags |= PSG_TEAMVOTED;
02270
02271 trap_Argv( 1, msg, sizeof( msg ) );
02272
02273 if ( msg[0] == 'y' || msg[1] == 'Y' || msg[1] == '1' ) {
02274 level.teamVoteYes[cs_offset]++;
02275 trap_SetConfigstring( CS_TEAMVOTE_YES + cs_offset, va("%i", level.teamVoteYes[cs_offset] ) );
02276 } else {
02277 level.teamVoteNo[cs_offset]++;
02278 trap_SetConfigstring( CS_TEAMVOTE_NO + cs_offset, va("%i", level.teamVoteNo[cs_offset] ) );
02279 }
02280
02281
02282
02283 }
02284
02285
02286
02287
02288
02289
02290
02291 void Cmd_SetViewpos_f( gentity_t *ent ) {
02292 vec3_t origin, angles;
02293 char buffer[MAX_TOKEN_CHARS];
02294 int i;
02295
02296 if ( !g_cheats.integer ) {
02297 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NOCHEATS")));
02298 return;
02299 }
02300 if ( trap_Argc() != 5 ) {
02301 trap_SendServerCommand( ent-g_entities, va("print \"usage: setviewpos x y z yaw\n\""));
02302 return;
02303 }
02304
02305 VectorClear( angles );
02306 for ( i = 0 ; i < 3 ; i++ ) {
02307 trap_Argv( i + 1, buffer, sizeof( buffer ) );
02308 origin[i] = atof( buffer );
02309 }
02310
02311 trap_Argv( 4, buffer, sizeof( buffer ) );
02312 angles[YAW] = atof( buffer );
02313
02314 TeleportPlayer( ent, origin, angles );
02315 }
02316
02317
02318
02319
02320
02321
02322
02323
02324 void Cmd_Stats_f( gentity_t *ent ) {
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339 }
02340
02341 int G_ItemUsable(playerState_t *ps, int forcedUse)
02342 {
02343 vec3_t fwd, fwdorg, dest, pos;
02344 vec3_t yawonly;
02345 vec3_t mins, maxs;
02346 vec3_t trtest;
02347 trace_t tr;
02348
02349 if (ps->m_iVehicleNum)
02350 {
02351 return 0;
02352 }
02353
02354 if (ps->pm_flags & PMF_USE_ITEM_HELD)
02355 {
02356 return 0;
02357 }
02358
02359 if (!forcedUse)
02360 {
02361 forcedUse = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag;
02362 }
02363
02364 if (!BG_IsItemSelectable(ps, forcedUse))
02365 {
02366 return 0;
02367 }
02368
02369 switch (forcedUse)
02370 {
02371 case HI_MEDPAC:
02372 case HI_MEDPAC_BIG:
02373 if (ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH])
02374 {
02375 return 0;
02376 }
02377
02378 if (ps->stats[STAT_HEALTH] <= 0)
02379 {
02380 return 0;
02381 }
02382
02383 return 1;
02384 case HI_SEEKER:
02385 if (ps->eFlags & EF_SEEKERDRONE)
02386 {
02387 G_AddEvent(&g_entities[ps->clientNum], EV_ITEMUSEFAIL, SEEKER_ALREADYDEPLOYED);
02388 return 0;
02389 }
02390
02391 return 1;
02392 case HI_SENTRY_GUN:
02393 if (ps->fd.sentryDeployed)
02394 {
02395 G_AddEvent(&g_entities[ps->clientNum], EV_ITEMUSEFAIL, SENTRY_ALREADYPLACED);
02396 return 0;
02397 }
02398
02399 yawonly[ROLL] = 0;
02400 yawonly[PITCH] = 0;
02401 yawonly[YAW] = ps->viewangles[YAW];
02402
02403 VectorSet( mins, -8, -8, 0 );
02404 VectorSet( maxs, 8, 8, 24 );
02405
02406 AngleVectors(yawonly, fwd, NULL, NULL);
02407
02408 fwdorg[0] = ps->origin[0] + fwd[0]*64;
02409 fwdorg[1] = ps->origin[1] + fwd[1]*64;
02410 fwdorg[2] = ps->origin[2] + fwd[2]*64;
02411
02412 trtest[0] = fwdorg[0] + fwd[0]*16;
02413 trtest[1] = fwdorg[1] + fwd[1]*16;
02414 trtest[2] = fwdorg[2] + fwd[2]*16;
02415
02416 trap_Trace(&tr, ps->origin, mins, maxs, trtest, ps->clientNum, MASK_PLAYERSOLID);
02417
02418 if ((tr.fraction != 1 && tr.entityNum != ps->clientNum) || tr.startsolid || tr.allsolid)
02419 {
02420 G_AddEvent(&g_entities[ps->clientNum], EV_ITEMUSEFAIL, SENTRY_NOROOM);
02421 return 0;
02422 }
02423
02424 return 1;
02425 case HI_SHIELD:
02426 mins[0] = -8;
02427 mins[1] = -8;
02428 mins[2] = 0;
02429
02430 maxs[0] = 8;
02431 maxs[1] = 8;
02432 maxs[2] = 8;
02433
02434 AngleVectors (ps->viewangles, fwd, NULL, NULL);
02435 fwd[2] = 0;
02436 VectorMA(ps->origin, 64, fwd, dest);
02437 trap_Trace(&tr, ps->origin, mins, maxs, dest, ps->clientNum, MASK_SHOT );
02438 if (tr.fraction > 0.9 && !tr.startsolid && !tr.allsolid)
02439 {
02440 VectorCopy(tr.endpos, pos);
02441 VectorSet( dest, pos[0], pos[1], pos[2] - 4096 );
02442 trap_Trace( &tr, pos, mins, maxs, dest, ps->clientNum, MASK_SOLID );
02443 if ( !tr.startsolid && !tr.allsolid )
02444 {
02445 return 1;
02446 }
02447 }
02448 G_AddEvent(&g_entities[ps->clientNum], EV_ITEMUSEFAIL, SHIELD_NOROOM);
02449 return 0;
02450 case HI_JETPACK:
02451 return 1;
02452 case HI_HEALTHDISP:
02453 return 1;
02454 case HI_AMMODISP:
02455 return 1;
02456 case HI_EWEB:
02457 return 1;
02458 case HI_CLOAK:
02459 return 1;
02460 default:
02461 return 1;
02462 }
02463 }
02464
02465 void saberKnockDown(gentity_t *saberent, gentity_t *saberOwner, gentity_t *other);
02466
02467 void Cmd_ToggleSaber_f(gentity_t *ent)
02468 {
02469 if (ent->client->ps.fd.forceGripCripple)
02470 {
02471 if (ent->client->ps.saberHolstered)
02472 {
02473 return;
02474 }
02475 }
02476
02477 if (ent->client->ps.saberInFlight)
02478 {
02479 if (ent->client->ps.saberEntityNum)
02480 {
02481 saberKnockDown(&g_entities[ent->client->ps.saberEntityNum], ent, ent);
02482 }
02483 return;
02484 }
02485
02486 if (ent->client->ps.forceHandExtend != HANDEXTEND_NONE)
02487 {
02488 return;
02489 }
02490
02491 if (ent->client->ps.weapon != WP_SABER)
02492 {
02493 return;
02494 }
02495
02496
02497
02498
02499
02500
02501 if (ent->client->ps.duelTime >= level.time)
02502 {
02503 return;
02504 }
02505
02506 if (ent->client->ps.saberLockTime >= level.time)
02507 {
02508 return;
02509 }
02510
02511 if (ent->client && ent->client->ps.weaponTime < 1)
02512 {
02513 if (ent->client->ps.saberHolstered == 2)
02514 {
02515 ent->client->ps.saberHolstered = 0;
02516
02517 if (ent->client->saber[0].soundOn)
02518 {
02519 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOn);
02520 }
02521 if (ent->client->saber[1].soundOn)
02522 {
02523 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOn);
02524 }
02525 }
02526 else
02527 {
02528 ent->client->ps.saberHolstered = 2;
02529 if (ent->client->saber[0].soundOff)
02530 {
02531 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOff);
02532 }
02533 if (ent->client->saber[1].soundOff &&
02534 ent->client->saber[1].model[0])
02535 {
02536 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02537 }
02538
02539 ent->client->ps.weaponTime = 400;
02540 }
02541 }
02542 }
02543
02544 extern vmCvar_t d_saberStanceDebug;
02545
02546 extern qboolean WP_SaberCanTurnOffSomeBlades( saberInfo_t *saber );
02547 void Cmd_SaberAttackCycle_f(gentity_t *ent)
02548 {
02549 int selectLevel = 0;
02550 qboolean usingSiegeStyle = qfalse;
02551
02552 if ( !ent || !ent->client )
02553 {
02554 return;
02555 }
02556
02557
02558
02559
02560
02561
02562
02563 if (ent->client->saber[0].model[0] && ent->client->saber[1].model[0])
02564 {
02565 if ( WP_SaberCanTurnOffSomeBlades( &ent->client->saber[1] ) )
02566 {
02567 if ( ent->client->ps.saberHolstered == 1 )
02568 {
02569
02570 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOn);
02571 ent->client->ps.saberHolstered = 0;
02572
02573 ent->client->ps.fd.saberAnimLevel = SS_DUAL;
02574 }
02575 else if ( ent->client->ps.saberHolstered == 0 )
02576 {
02577 if ( (ent->client->saber[1].saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) )
02578 {
02579 }
02580 else if ( ent->client->saber[1].bladeStyle2Start > 0
02581 && (ent->client->saber[1].saberFlags2&SFL2_NO_MANUAL_DEACTIVATE2) )
02582 {
02583 }
02584 else
02585 {
02586
02587 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02588 ent->client->ps.saberHolstered = 1;
02589
02590 ent->client->ps.fd.saberAnimLevel = SS_FAST;
02591 }
02592 }
02593
02594 if (d_saberStanceDebug.integer)
02595 {
02596 trap_SendServerCommand( ent-g_entities, va("print \"SABERSTANCEDEBUG: Attempted to toggle dual saber blade.\n\"") );
02597 }
02598 return;
02599 }
02600 }
02601 else if (ent->client->saber[0].numBlades > 1
02602 && WP_SaberCanTurnOffSomeBlades( &ent->client->saber[0] ) )
02603 {
02604 if ( ent->client->ps.saberHolstered == 1 )
02605 {
02606 if ( ent->client->ps.saberInFlight )
02607 {
02608 if (d_saberStanceDebug.integer)
02609 {
02610 trap_SendServerCommand( ent-g_entities, va("print \"SABERSTANCEDEBUG: Attempted to toggle staff blade in air.\n\"") );
02611 }
02612 return;
02613 }
02614
02615 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOn);
02616 ent->client->ps.saberHolstered = 0;
02617
02618 if ( ent->client->saber[0].stylesForbidden )
02619 {
02620 WP_UseFirstValidSaberStyle( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, &selectLevel );
02621 if ( ent->client->ps.weaponTime <= 0 )
02622 {
02623 ent->client->ps.fd.saberAnimLevel = selectLevel;
02624 }
02625 else
02626 {
02627 ent->client->saberCycleQueue = selectLevel;
02628 }
02629 }
02630 }
02631 else if ( ent->client->ps.saberHolstered == 0 )
02632 {
02633 if ( (ent->client->saber[0].saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) )
02634 {
02635 }
02636 else if ( ent->client->saber[0].bladeStyle2Start > 0
02637 && (ent->client->saber[0].saberFlags2&SFL2_NO_MANUAL_DEACTIVATE2) )
02638 {
02639 }
02640 else
02641 {
02642
02643 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOff);
02644 ent->client->ps.saberHolstered = 1;
02645
02646 if ( ent->client->saber[0].singleBladeStyle != SS_NONE )
02647 {
02648 if ( ent->client->ps.weaponTime <= 0 )
02649 {
02650 ent->client->ps.fd.saberAnimLevel = ent->client->saber[0].singleBladeStyle;
02651 }
02652 else
02653 {
02654 ent->client->saberCycleQueue = ent->client->saber[0].singleBladeStyle;
02655 }
02656 }
02657 }
02658 }
02659 if (d_saberStanceDebug.integer)
02660 {
02661 trap_SendServerCommand( ent-g_entities, va("print \"SABERSTANCEDEBUG: Attempted to toggle staff blade.\n\"") );
02662 }
02663 return;
02664 }
02665
02666 if (ent->client->saberCycleQueue)
02667 {
02668 selectLevel = ent->client->saberCycleQueue;
02669 }
02670 else
02671 {
02672 selectLevel = ent->client->ps.fd.saberAnimLevel;
02673 }
02674
02675 if (g_gametype.integer == GT_SIEGE &&
02676 ent->client->siegeClass != -1 &&
02677 bgSiegeClasses[ent->client->siegeClass].saberStance)
02678 {
02679 int i = selectLevel+1;
02680
02681 usingSiegeStyle = qtrue;
02682
02683 while (i != selectLevel)
02684 {
02685 if (i >= SS_NUM_SABER_STYLES)
02686 {
02687 i = SS_FAST;
02688 }
02689
02690 if (bgSiegeClasses[ent->client->siegeClass].saberStance & (1 << i))
02691 {
02692 selectLevel = i;
02693 break;
02694 }
02695 i++;
02696 }
02697
02698 if (d_saberStanceDebug.integer)
02699 {
02700 trap_SendServerCommand( ent-g_entities, va("print \"SABERSTANCEDEBUG: Attempted to cycle given class stance.\n\"") );
02701 }
02702 }
02703 else
02704 {
02705 selectLevel++;
02706 if ( selectLevel > ent->client->ps.fd.forcePowerLevel[FP_SABER_OFFENSE] )
02707 {
02708 selectLevel = FORCE_LEVEL_1;
02709 }
02710 if (d_saberStanceDebug.integer)
02711 {
02712 trap_SendServerCommand( ent-g_entities, va("print \"SABERSTANCEDEBUG: Attempted to cycle stance normally.\n\"") );
02713 }
02714 }
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731 if ( !usingSiegeStyle )
02732 {
02733
02734 WP_UseFirstValidSaberStyle( &ent->client->saber[0], &ent->client->saber[1], ent->client->ps.saberHolstered, &selectLevel );
02735 }
02736
02737 if (ent->client->ps.weaponTime <= 0)
02738 {
02739 ent->client->ps.fd.saberAnimLevelBase = ent->client->ps.fd.saberAnimLevel = selectLevel;
02740 }
02741 else
02742 {
02743 ent->client->ps.fd.saberAnimLevelBase = ent->client->saberCycleQueue = selectLevel;
02744 }
02745 }
02746
02747 qboolean G_OtherPlayersDueling(void)
02748 {
02749 int i = 0;
02750 gentity_t *ent;
02751
02752 while (i < MAX_CLIENTS)
02753 {
02754 ent = &g_entities[i];
02755
02756 if (ent && ent->inuse && ent->client && ent->client->ps.duelInProgress)
02757 {
02758 return qtrue;
02759 }
02760 i++;
02761 }
02762
02763 return qfalse;
02764 }
02765
02766 void Cmd_EngageDuel_f(gentity_t *ent)
02767 {
02768 trace_t tr;
02769 vec3_t forward, fwdOrg;
02770
02771 if (!g_privateDuel.integer)
02772 {
02773 return;
02774 }
02775
02776 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
02777 {
02778 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NODUEL_GAMETYPE")) );
02779 return;
02780 }
02781
02782
02783 if (g_gametype.integer >= GT_TEAM)
02784 {
02785 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NODUEL_GAMETYPE")) );
02786 return;
02787 }
02788
02789 if (ent->client->ps.duelTime >= level.time)
02790 {
02791 return;
02792 }
02793
02794 if (ent->client->ps.weapon != WP_SABER)
02795 {
02796 return;
02797 }
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807 if (ent->client->ps.saberInFlight)
02808 {
02809 return;
02810 }
02811
02812 if (ent->client->ps.duelInProgress)
02813 {
02814 return;
02815 }
02816
02817
02818 if (ent->client->ps.fd.privateDuelTime > level.time)
02819 {
02820 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "CANTDUEL_JUSTDID")) );
02821 return;
02822 }
02823
02824 if (G_OtherPlayersDueling())
02825 {
02826 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "CANTDUEL_BUSY")) );
02827 return;
02828 }
02829
02830 AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL );
02831
02832 fwdOrg[0] = ent->client->ps.origin[0] + forward[0]*256;
02833 fwdOrg[1] = ent->client->ps.origin[1] + forward[1]*256;
02834 fwdOrg[2] = (ent->client->ps.origin[2]+ent->client->ps.viewheight) + forward[2]*256;
02835
02836 trap_Trace(&tr, ent->client->ps.origin, NULL, NULL, fwdOrg, ent->s.number, MASK_PLAYERSOLID);
02837
02838 if (tr.fraction != 1 && tr.entityNum < MAX_CLIENTS)
02839 {
02840 gentity_t *challenged = &g_entities[tr.entityNum];
02841
02842 if (!challenged || !challenged->client || !challenged->inuse ||
02843 challenged->health < 1 || challenged->client->ps.stats[STAT_HEALTH] < 1 ||
02844 challenged->client->ps.weapon != WP_SABER || challenged->client->ps.duelInProgress ||
02845 challenged->client->ps.saberInFlight)
02846 {
02847 return;
02848 }
02849
02850 if (g_gametype.integer >= GT_TEAM && OnSameTeam(ent, challenged))
02851 {
02852 return;
02853 }
02854
02855 if (challenged->client->ps.duelIndex == ent->s.number && challenged->client->ps.duelTime >= level.time)
02856 {
02857 trap_SendServerCommand( -1, va("print \"%s %s %s!\n\"", challenged->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELACCEPT"), ent->client->pers.netname) );
02858
02859 ent->client->ps.duelInProgress = qtrue;
02860 challenged->client->ps.duelInProgress = qtrue;
02861
02862 ent->client->ps.duelTime = level.time + 2000;
02863 challenged->client->ps.duelTime = level.time + 2000;
02864
02865 G_AddEvent(ent, EV_PRIVATE_DUEL, 1);
02866 G_AddEvent(challenged, EV_PRIVATE_DUEL, 1);
02867
02868
02869
02870 if (!ent->client->ps.saberHolstered)
02871 {
02872 if (ent->client->saber[0].soundOff)
02873 {
02874 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOff);
02875 }
02876 if (ent->client->saber[1].soundOff &&
02877 ent->client->saber[1].model[0])
02878 {
02879 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02880 }
02881 ent->client->ps.weaponTime = 400;
02882 ent->client->ps.saberHolstered = 2;
02883 }
02884 if (!challenged->client->ps.saberHolstered)
02885 {
02886 if (challenged->client->saber[0].soundOff)
02887 {
02888 G_Sound(challenged, CHAN_AUTO, challenged->client->saber[0].soundOff);
02889 }
02890 if (challenged->client->saber[1].soundOff &&
02891 challenged->client->saber[1].model[0])
02892 {
02893 G_Sound(challenged, CHAN_AUTO, challenged->client->saber[1].soundOff);
02894 }
02895 challenged->client->ps.weaponTime = 400;
02896 challenged->client->ps.saberHolstered = 2;
02897 }
02898 }
02899 else
02900 {
02901
02902 trap_SendServerCommand( challenged-g_entities, va("cp \"%s %s\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELCHALLENGE")) );
02903 trap_SendServerCommand( ent-g_entities, va("cp \"%s %s\n\"", G_GetStringEdString("MP_SVGAME", "PLDUELCHALLENGED"), challenged->client->pers.netname) );
02904 }
02905
02906 challenged->client->ps.fd.privateDuelTime = 0;
02907
02908 ent->client->ps.forceHandExtend = HANDEXTEND_DUELCHALLENGE;
02909 ent->client->ps.forceHandExtendTime = level.time + 1000;
02910
02911 ent->client->ps.duelIndex = challenged->s.number;
02912 ent->client->ps.duelTime = level.time + 5000;
02913 }
02914 }
02915
02916 #ifndef FINAL_BUILD
02917 extern stringID_table_t animTable[MAX_ANIMATIONS+1];
02918
02919 void Cmd_DebugSetSaberMove_f(gentity_t *self)
02920 {
02921 int argNum = trap_Argc();
02922 char arg[MAX_STRING_CHARS];
02923
02924 if (argNum < 2)
02925 {
02926 return;
02927 }
02928
02929 trap_Argv( 1, arg, sizeof( arg ) );
02930
02931 if (!arg[0])
02932 {
02933 return;
02934 }
02935
02936 self->client->ps.saberMove = atoi(arg);
02937 self->client->ps.saberBlocked = BLOCKED_BOUNCE_MOVE;
02938
02939 if (self->client->ps.saberMove >= LS_MOVE_MAX)
02940 {
02941 self->client->ps.saberMove = LS_MOVE_MAX-1;
02942 }
02943
02944 Com_Printf("Anim for move: %s\n", animTable[saberMoveData[self->client->ps.saberMove].animToUse].name);
02945 }
02946
02947 void Cmd_DebugSetBodyAnim_f(gentity_t *self, int flags)
02948 {
02949 int argNum = trap_Argc();
02950 char arg[MAX_STRING_CHARS];
02951 int i = 0;
02952
02953 if (argNum < 2)
02954 {
02955 return;
02956 }
02957
02958 trap_Argv( 1, arg, sizeof( arg ) );
02959
02960 if (!arg[0])
02961 {
02962 return;
02963 }
02964
02965 while (i < MAX_ANIMATIONS)
02966 {
02967 if (!Q_stricmp(arg, animTable[i].name))
02968 {
02969 break;
02970 }
02971 i++;
02972 }
02973
02974 if (i == MAX_ANIMATIONS)
02975 {
02976 Com_Printf("Animation '%s' does not exist\n", arg);
02977 return;
02978 }
02979
02980 G_SetAnim(self, NULL, SETANIM_BOTH, i, flags, 0);
02981
02982 Com_Printf("Set body anim to %s\n", arg);
02983 }
02984 #endif
02985
02986 void StandardSetBodyAnim(gentity_t *self, int anim, int flags)
02987 {
02988 G_SetAnim(self, NULL, SETANIM_BOTH, anim, flags, 0);
02989 }
02990
02991 void DismembermentTest(gentity_t *self);
02992
02993 void Bot_SetForcedMovement(int bot, int forward, int right, int up);
02994
02995 #ifndef FINAL_BUILD
02996 extern void DismembermentByNum(gentity_t *self, int num);
02997 extern void G_SetVehDamageFlags( gentity_t *veh, int shipSurf, int damageLevel );
02998 #endif
02999
03000 static int G_ClientNumFromNetname(char *name)
03001 {
03002 int i = 0;
03003 gentity_t *ent;
03004
03005 while (i < MAX_CLIENTS)
03006 {
03007 ent = &g_entities[i];
03008
03009 if (ent->inuse && ent->client &&
03010 !Q_stricmp(ent->client->pers.netname, name))
03011 {
03012 return ent->s.number;
03013 }
03014 i++;
03015 }
03016
03017 return -1;
03018 }
03019
03020 qboolean TryGrapple(gentity_t *ent)
03021 {
03022 if (ent->client->ps.weaponTime > 0)
03023 {
03024 return qfalse;
03025 }
03026 if (ent->client->ps.forceHandExtend != HANDEXTEND_NONE)
03027 {
03028 return qfalse;
03029 }
03030 if (ent->client->grappleState)
03031 {
03032 return qfalse;
03033 }
03034
03035 if (ent->client->ps.weapon != WP_SABER && ent->client->ps.weapon != WP_MELEE)
03036 {
03037 return qfalse;
03038 }
03039
03040 if (ent->client->ps.weapon == WP_SABER && !ent->client->ps.saberHolstered)
03041 {
03042 Cmd_ToggleSaber_f(ent);
03043 if (!ent->client->ps.saberHolstered)
03044 {
03045 return qfalse;
03046 }
03047 }
03048
03049
03050 G_SetAnim(ent, &ent->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_GRAB, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0);
03051 if (ent->client->ps.torsoAnim == BOTH_KYLE_GRAB)
03052 {
03053 ent->client->ps.torsoTimer += 500;
03054 if (ent->client->ps.legsAnim == ent->client->ps.torsoAnim)
03055 {
03056 ent->client->ps.legsTimer = ent->client->ps.torsoTimer;
03057 }
03058 ent->client->ps.weaponTime = ent->client->ps.torsoTimer;
03059 return qtrue;
03060 }
03061
03062 return qfalse;
03063 }
03064
03065 #ifndef FINAL_BUILD
03066 qboolean saberKnockOutOfHand(gentity_t *saberent, gentity_t *saberOwner, vec3_t velocity);
03067 #endif
03068
03069
03070
03071
03072
03073
03074 void ClientCommand( int clientNum ) {
03075 gentity_t *ent;
03076 char cmd[MAX_TOKEN_CHARS];
03077
03078 ent = g_entities + clientNum;
03079 if ( !ent->client ) {
03080 return;
03081 }
03082
03083
03084 trap_Argv( 0, cmd, sizeof( cmd ) );
03085
03086
03087 if (strstr(cmd, "bot_") && AcceptBotCommand(cmd, ent))
03088 {
03089 return;
03090 }
03091
03092
03093 if (Q_stricmp (cmd, "say") == 0) {
03094 Cmd_Say_f (ent, SAY_ALL, qfalse);
03095 return;
03096 }
03097 if (Q_stricmp (cmd, "say_team") == 0) {
03098 if (g_gametype.integer < GT_TEAM)
03099 {
03100 Cmd_Say_f (ent, SAY_ALL, qfalse);
03101 }
03102 else
03103 {
03104 Cmd_Say_f (ent, SAY_TEAM, qfalse);
03105 }
03106 return;
03107 }
03108 if (Q_stricmp (cmd, "tell") == 0) {
03109 Cmd_Tell_f ( ent );
03110 return;
03111 }
03112
03113 if (Q_stricmp(cmd, "voice_cmd") == 0)
03114 {
03115 Cmd_VoiceCommand_f(ent);
03116 return;
03117 }
03118
03119 if (Q_stricmp (cmd, "score") == 0) {
03120 Cmd_Score_f (ent);
03121 return;
03122 }
03123
03124
03125 if (level.intermissiontime)
03126 {
03127 qboolean giveError = qfalse;
03128
03129
03130 if (!Q_stricmp(cmd, "give"))
03131 {
03132 giveError = qtrue;
03133 }
03134 else if (!Q_stricmp(cmd, "giveother"))
03135 {
03136 giveError = qtrue;
03137 }
03138 else if (!Q_stricmp(cmd, "god"))
03139 {
03140 giveError = qtrue;
03141 }
03142 else if (!Q_stricmp(cmd, "notarget"))
03143 {
03144 giveError = qtrue;
03145 }
03146 else if (!Q_stricmp(cmd, "noclip"))
03147 {
03148 giveError = qtrue;
03149 }
03150 else if (!Q_stricmp(cmd, "kill"))
03151 {
03152 giveError = qtrue;
03153 }
03154 else if (!Q_stricmp(cmd, "teamtask"))
03155 {
03156 giveError = qtrue;
03157 }
03158 else if (!Q_stricmp(cmd, "levelshot"))
03159 {
03160 giveError = qtrue;
03161 }
03162 else if (!Q_stricmp(cmd, "follow"))
03163 {
03164 giveError = qtrue;
03165 }
03166 else if (!Q_stricmp(cmd, "follownext"))
03167 {
03168 giveError = qtrue;
03169 }
03170 else if (!Q_stricmp(cmd, "followprev"))
03171 {
03172 giveError = qtrue;
03173 }
03174 else if (!Q_stricmp(cmd, "team"))
03175 {
03176 giveError = qtrue;
03177 }
03178 else if (!Q_stricmp(cmd, "duelteam"))
03179 {
03180 giveError = qtrue;
03181 }
03182 else if (!Q_stricmp(cmd, "siegeclass"))
03183 {
03184 giveError = qtrue;
03185 }
03186 else if (!Q_stricmp(cmd, "forcechanged"))
03187 {
03188 Cmd_ForceChanged_f (ent);
03189 return;
03190 }
03191 else if (!Q_stricmp(cmd, "where"))
03192 {
03193 giveError = qtrue;
03194 }
03195 else if (!Q_stricmp(cmd, "callvote"))
03196 {
03197 giveError = qtrue;
03198 }
03199 else if (!Q_stricmp(cmd, "vote"))
03200 {
03201 giveError = qtrue;
03202 }
03203 else if (!Q_stricmp(cmd, "callteamvote"))
03204 {
03205 giveError = qtrue;
03206 }
03207 else if (!Q_stricmp(cmd, "teamvote"))
03208 {
03209 giveError = qtrue;
03210 }
03211 else if (!Q_stricmp(cmd, "gc"))
03212 {
03213 giveError = qtrue;
03214 }
03215 else if (!Q_stricmp(cmd, "setviewpos"))
03216 {
03217 giveError = qtrue;
03218 }
03219 else if (!Q_stricmp(cmd, "stats"))
03220 {
03221 giveError = qtrue;
03222 }
03223
03224 if (giveError)
03225 {
03226 trap_SendServerCommand( clientNum, va("print \"%s (%s) \n\"", G_GetStringEdString("MP_SVGAME", "CANNOT_TASK_INTERMISSION"), cmd ) );
03227 }
03228 else
03229 {
03230 Cmd_Say_f (ent, qfalse, qtrue);
03231 }
03232 return;
03233 }
03234
03235 if (Q_stricmp (cmd, "give") == 0)
03236 {
03237 Cmd_Give_f (ent, 0);
03238 }
03239 else if (Q_stricmp (cmd, "giveother") == 0)
03240 {
03241 Cmd_Give_f (ent, 1);
03242 }
03243 else if (Q_stricmp (cmd, "t_use") == 0 && CheatsOk(ent))
03244 {
03245 if (trap_Argc() > 1)
03246 {
03247 char sArg[MAX_STRING_CHARS];
03248 gentity_t *targ;
03249
03250 trap_Argv( 1, sArg, sizeof( sArg ) );
03251 targ = G_Find( NULL, FOFS(targetname), sArg );
03252
03253 while (targ)
03254 {
03255 if (targ->use)
03256 {
03257 targ->use(targ, ent, ent);
03258 }
03259 targ = G_Find( targ, FOFS(targetname), sArg );
03260 }
03261 }
03262 }
03263 else if (Q_stricmp (cmd, "god") == 0)
03264 Cmd_God_f (ent);
03265 else if (Q_stricmp (cmd, "notarget") == 0)
03266 Cmd_Notarget_f (ent);
03267 else if (Q_stricmp (cmd, "noclip") == 0)
03268 Cmd_Noclip_f (ent);
03269 else if ( Q_stricmp( cmd, "NPC" ) == 0 && CheatsOk(ent) )
03270 {
03271 Cmd_NPC_f( ent );
03272 }
03273 else if (Q_stricmp (cmd, "kill") == 0)
03274 Cmd_Kill_f (ent);
03275 else if (Q_stricmp (cmd, "teamtask") == 0)
03276 Cmd_TeamTask_f (ent);
03277 else if (Q_stricmp (cmd, "levelshot") == 0)
03278 Cmd_LevelShot_f (ent);
03279 else if (Q_stricmp (cmd, "follow") == 0)
03280 Cmd_Follow_f (ent);
03281 else if (Q_stricmp (cmd, "follownext") == 0)
03282 Cmd_FollowCycle_f (ent, 1);
03283 else if (Q_stricmp (cmd, "followprev") == 0)
03284 Cmd_FollowCycle_f (ent, -1);
03285 else if (Q_stricmp (cmd, "team") == 0)
03286 Cmd_Team_f (ent);
03287 else if (Q_stricmp (cmd, "duelteam") == 0)
03288 Cmd_DuelTeam_f (ent);
03289 else if (Q_stricmp (cmd, "siegeclass") == 0)
03290 Cmd_SiegeClass_f (ent);
03291 else if (Q_stricmp (cmd, "forcechanged") == 0)
03292 Cmd_ForceChanged_f (ent);
03293 else if (Q_stricmp (cmd, "where") == 0)
03294 Cmd_Where_f (ent);
03295 else if (Q_stricmp (cmd, "callvote") == 0)
03296 Cmd_CallVote_f (ent);
03297 else if (Q_stricmp (cmd, "vote") == 0)
03298 Cmd_Vote_f (ent);
03299 else if (Q_stricmp (cmd, "callteamvote") == 0)
03300 Cmd_CallTeamVote_f (ent);
03301 else if (Q_stricmp (cmd, "teamvote") == 0)
03302 Cmd_TeamVote_f (ent);
03303 else if (Q_stricmp (cmd, "gc") == 0)
03304 Cmd_GameCommand_f( ent );
03305 else if (Q_stricmp (cmd, "setviewpos") == 0)
03306 Cmd_SetViewpos_f( ent );
03307 else if (Q_stricmp (cmd, "stats") == 0)
03308 Cmd_Stats_f( ent );
03309
03310
03311
03312
03313
03314
03315
03316 else if (Q_stricmp(cmd, "killother") == 0 && CheatsOk( ent ))
03317 {
03318 if (trap_Argc() > 1)
03319 {
03320 char sArg[MAX_STRING_CHARS];
03321 int entNum = 0;
03322
03323 trap_Argv( 1, sArg, sizeof( sArg ) );
03324
03325 entNum = G_ClientNumFromNetname(sArg);
03326
03327 if (entNum >= 0 && entNum < MAX_GENTITIES)
03328 {
03329 gentity_t *kEnt = &g_entities[entNum];
03330
03331 if (kEnt->inuse && kEnt->client)
03332 {
03333 kEnt->flags &= ~FL_GODMODE;
03334 kEnt->client->ps.stats[STAT_HEALTH] = kEnt->health = -999;
03335 player_die (kEnt, kEnt, kEnt, 100000, MOD_SUICIDE);
03336 }
03337 }
03338 }
03339 }
03340 #ifdef _DEBUG
03341 else if (Q_stricmp(cmd, "relax") == 0 && CheatsOk( ent ))
03342 {
03343 if (ent->client->ps.eFlags & EF_RAG)
03344 {
03345 ent->client->ps.eFlags &= ~EF_RAG;
03346 }
03347 else
03348 {
03349 ent->client->ps.eFlags |= EF_RAG;
03350 }
03351 }
03352 else if (Q_stricmp(cmd, "holdme") == 0 && CheatsOk( ent ))
03353 {
03354 if (trap_Argc() > 1)
03355 {
03356 char sArg[MAX_STRING_CHARS];
03357 int entNum = 0;
03358
03359 trap_Argv( 1, sArg, sizeof( sArg ) );
03360
03361 entNum = atoi(sArg);
03362
03363 if (entNum >= 0 &&
03364 entNum < MAX_GENTITIES)
03365 {
03366 gentity_t *grabber = &g_entities[entNum];
03367
03368 if (grabber->inuse && grabber->client && grabber->ghoul2)
03369 {
03370 if (!grabber->s.number)
03371 {
03372 ent->client->ps.ragAttach = ENTITYNUM_NONE;
03373 }
03374 else
03375 {
03376 ent->client->ps.ragAttach = grabber->s.number;
03377 }
03378 }
03379 }
03380 }
03381 else
03382 {
03383 ent->client->ps.ragAttach = 0;
03384 }
03385 }
03386 else if (Q_stricmp(cmd, "limb_break") == 0 && CheatsOk( ent ))
03387 {
03388 if (trap_Argc() > 1)
03389 {
03390 char sArg[MAX_STRING_CHARS];
03391 int breakLimb = 0;
03392
03393 trap_Argv( 1, sArg, sizeof( sArg ) );
03394 if (!Q_stricmp(sArg, "right"))
03395 {
03396 breakLimb = BROKENLIMB_RARM;
03397 }
03398 else if (!Q_stricmp(sArg, "left"))
03399 {
03400 breakLimb = BROKENLIMB_LARM;
03401 }
03402
03403 G_BreakArm(ent, breakLimb);
03404 }
03405 }
03406 else if (Q_stricmp(cmd, "headexplodey") == 0 && CheatsOk( ent ))
03407 {
03408 Cmd_Kill_f (ent);
03409 if (ent->health < 1)
03410 {
03411 DismembermentTest(ent);
03412 }
03413 }
03414 else if (Q_stricmp(cmd, "debugstupidthing") == 0 && CheatsOk( ent ))
03415 {
03416 int i = 0;
03417 gentity_t *blah;
03418 while (i < MAX_GENTITIES)
03419 {
03420 blah = &g_entities[i];
03421 if (blah->inuse && blah->classname && blah->classname[0] && !Q_stricmp(blah->classname, "NPC_Vehicle"))
03422 {
03423 Com_Printf("Found it.\n");
03424 }
03425 i++;
03426 }
03427 }
03428 else if (Q_stricmp(cmd, "arbitraryprint") == 0 && CheatsOk( ent ))
03429 {
03430 trap_SendServerCommand( -1, va("cp \"Blah blah blah\n\""));
03431 }
03432 else if (Q_stricmp(cmd, "handcut") == 0 && CheatsOk( ent ))
03433 {
03434 int bCl = 0;
03435 char sarg[MAX_STRING_CHARS];
03436
03437 if (trap_Argc() > 1)
03438 {
03439 trap_Argv( 1, sarg, sizeof( sarg ) );
03440
03441 if (sarg[0])
03442 {
03443 bCl = atoi(sarg);
03444
03445 if (bCl >= 0 && bCl < MAX_GENTITIES)
03446 {
03447 gentity_t *hEnt = &g_entities[bCl];
03448
03449 if (hEnt->client)
03450 {
03451 if (hEnt->health > 0)
03452 {
03453 gGAvoidDismember = 1;
03454 hEnt->flags &= ~FL_GODMODE;
03455 hEnt->client->ps.stats[STAT_HEALTH] = hEnt->health = -999;
03456 player_die (hEnt, hEnt, hEnt, 100000, MOD_SUICIDE);
03457 }
03458 gGAvoidDismember = 2;
03459 G_CheckForDismemberment(hEnt, ent, hEnt->client->ps.origin, 999, hEnt->client->ps.legsAnim, qfalse);
03460 gGAvoidDismember = 0;
03461 }
03462 }
03463 }
03464 }
03465 }
03466 else if (Q_stricmp(cmd, "loveandpeace") == 0 && CheatsOk( ent ))
03467 {
03468 trace_t tr;
03469 vec3_t fPos;
03470
03471 AngleVectors(ent->client->ps.viewangles, fPos, 0, 0);
03472
03473 fPos[0] = ent->client->ps.origin[0] + fPos[0]*40;
03474 fPos[1] = ent->client->ps.origin[1] + fPos[1]*40;
03475 fPos[2] = ent->client->ps.origin[2] + fPos[2]*40;
03476
03477 trap_Trace(&tr, ent->client->ps.origin, 0, 0, fPos, ent->s.number, ent->clipmask);
03478
03479 if (tr.entityNum < MAX_CLIENTS && tr.entityNum != ent->s.number)
03480 {
03481 gentity_t *other = &g_entities[tr.entityNum];
03482
03483 if (other && other->inuse && other->client)
03484 {
03485 vec3_t entDir;
03486 vec3_t otherDir;
03487 vec3_t entAngles;
03488 vec3_t otherAngles;
03489
03490 if (ent->client->ps.weapon == WP_SABER && !ent->client->ps.saberHolstered)
03491 {
03492 Cmd_ToggleSaber_f(ent);
03493 }
03494
03495 if (other->client->ps.weapon == WP_SABER && !other->client->ps.saberHolstered)
03496 {
03497 Cmd_ToggleSaber_f(other);
03498 }
03499
03500 if ((ent->client->ps.weapon != WP_SABER || ent->client->ps.saberHolstered) &&
03501 (other->client->ps.weapon != WP_SABER || other->client->ps.saberHolstered))
03502 {
03503 VectorSubtract( other->client->ps.origin, ent->client->ps.origin, otherDir );
03504 VectorCopy( ent->client->ps.viewangles, entAngles );
03505 entAngles[YAW] = vectoyaw( otherDir );
03506 SetClientViewAngle( ent, entAngles );
03507
03508 StandardSetBodyAnim(ent, BOTH_STAND1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS);
03509 ent->client->ps.saberMove = LS_NONE;
03510 ent->client->ps.saberBlocked = 0;
03511 ent->client->ps.saberBlocking = 0;
03512
03513 VectorSubtract( ent->client->ps.origin, other->client->ps.origin, entDir );
03514 VectorCopy( other->client->ps.viewangles, otherAngles );
03515 otherAngles[YAW] = vectoyaw( entDir );
03516 SetClientViewAngle( other, otherAngles );
03517
03518 StandardSetBodyAnim(other, BOTH_STAND1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_HOLDLESS);
03519 other->client->ps.saberMove = LS_NONE;
03520 other->client->ps.saberBlocked = 0;
03521 other->client->ps.saberBlocking = 0;
03522 }
03523 }
03524 }
03525 }
03526 #endif
03527 else if (Q_stricmp(cmd, "thedestroyer") == 0 && CheatsOk( ent ) && ent && ent->client && ent->client->ps.saberHolstered && ent->client->ps.weapon == WP_SABER)
03528 {
03529 Cmd_ToggleSaber_f(ent);
03530
03531 if (!ent->client->ps.saberHolstered)
03532 {
03533 }
03534 }
03535
03536 else if (Q_stricmp(cmd, "debugBMove_Forward") == 0 && CheatsOk(ent))
03537 {
03538 int arg = 4000;
03539 int bCl = 0;
03540 char sarg[MAX_STRING_CHARS];
03541
03542 assert(trap_Argc() > 1);
03543 trap_Argv( 1, sarg, sizeof( sarg ) );
03544
03545 assert(sarg[0]);
03546 bCl = atoi(sarg);
03547 Bot_SetForcedMovement(bCl, arg, -1, -1);
03548 }
03549 else if (Q_stricmp(cmd, "debugBMove_Back") == 0 && CheatsOk(ent))
03550 {
03551 int arg = -4000;
03552 int bCl = 0;
03553 char sarg[MAX_STRING_CHARS];
03554
03555 assert(trap_Argc() > 1);
03556 trap_Argv( 1, sarg, sizeof( sarg ) );
03557
03558 assert(sarg[0]);
03559 bCl = atoi(sarg);
03560 Bot_SetForcedMovement(bCl, arg, -1, -1);
03561 }
03562 else if (Q_stricmp(cmd, "debugBMove_Right") == 0 && CheatsOk(ent))
03563 {
03564 int arg = 4000;
03565 int bCl = 0;
03566 char sarg[MAX_STRING_CHARS];
03567
03568 assert(trap_Argc() > 1);
03569 trap_Argv( 1, sarg, sizeof( sarg ) );
03570
03571 assert(sarg[0]);
03572 bCl = atoi(sarg);
03573 Bot_SetForcedMovement(bCl, -1, arg, -1);
03574 }
03575 else if (Q_stricmp(cmd, "debugBMove_Left") == 0 && CheatsOk(ent))
03576 {
03577 int arg = -4000;
03578 int bCl = 0;
03579 char sarg[MAX_STRING_CHARS];
03580
03581 assert(trap_Argc() > 1);
03582 trap_Argv( 1, sarg, sizeof( sarg ) );
03583
03584 assert(sarg[0]);
03585 bCl = atoi(sarg);
03586 Bot_SetForcedMovement(bCl, -1, arg, -1);
03587 }
03588 else if (Q_stricmp(cmd, "debugBMove_Up") == 0 && CheatsOk(ent))
03589 {
03590 int arg = 4000;
03591 int bCl = 0;
03592 char sarg[MAX_STRING_CHARS];
03593
03594 assert(trap_Argc() > 1);
03595 trap_Argv( 1, sarg, sizeof( sarg ) );
03596
03597 assert(sarg[0]);
03598 bCl = atoi(sarg);
03599 Bot_SetForcedMovement(bCl, -1, -1, arg);
03600 }
03601
03602 #ifndef FINAL_BUILD
03603 else if (Q_stricmp(cmd, "debugSetSaberMove") == 0)
03604 {
03605 Cmd_DebugSetSaberMove_f(ent);
03606 }
03607 else if (Q_stricmp(cmd, "debugSetBodyAnim") == 0)
03608 {
03609 Cmd_DebugSetBodyAnim_f(ent, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
03610 }
03611 else if (Q_stricmp(cmd, "debugDismemberment") == 0)
03612 {
03613 Cmd_Kill_f (ent);
03614 if (ent->health < 1)
03615 {
03616 char arg[MAX_STRING_CHARS];
03617 int iArg = 0;
03618
03619 if (trap_Argc() > 1)
03620 {
03621 trap_Argv( 1, arg, sizeof( arg ) );
03622
03623 if (arg[0])
03624 {
03625 iArg = atoi(arg);
03626 }
03627 }
03628
03629 DismembermentByNum(ent, iArg);
03630 }
03631 }
03632 else if (Q_stricmp(cmd, "debugDropSaber") == 0)
03633 {
03634 if (ent->client->ps.weapon == WP_SABER &&
03635 ent->client->ps.saberEntityNum &&
03636 !ent->client->ps.saberInFlight)
03637 {
03638 saberKnockOutOfHand(&g_entities[ent->client->ps.saberEntityNum], ent, vec3_origin);
03639 }
03640 }
03641 else if (Q_stricmp(cmd, "debugKnockMeDown") == 0)
03642 {
03643 if (BG_KnockDownable(&ent->client->ps))
03644 {
03645 ent->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
03646 ent->client->ps.forceDodgeAnim = 0;
03647 if (trap_Argc() > 1)
03648 {
03649 ent->client->ps.forceHandExtendTime = level.time + 1100;
03650 ent->client->ps.quickerGetup = qfalse;
03651 }
03652 else
03653 {
03654 ent->client->ps.forceHandExtendTime = level.time + 700;
03655 ent->client->ps.quickerGetup = qtrue;
03656 }
03657 }
03658 }
03659 else if (Q_stricmp(cmd, "debugSaberSwitch") == 0)
03660 {
03661 gentity_t *targ = NULL;
03662
03663 if (trap_Argc() > 1)
03664 {
03665 char arg[MAX_STRING_CHARS];
03666
03667 trap_Argv( 1, arg, sizeof( arg ) );
03668
03669 if (arg[0])
03670 {
03671 int x = atoi(arg);
03672
03673 if (x >= 0 && x < MAX_CLIENTS)
03674 {
03675 targ = &g_entities[x];
03676 }
03677 }
03678 }
03679
03680 if (targ && targ->inuse && targ->client)
03681 {
03682 Cmd_ToggleSaber_f(targ);
03683 }
03684 }
03685 else if (Q_stricmp(cmd, "debugIKGrab") == 0)
03686 {
03687 gentity_t *targ = NULL;
03688
03689 if (trap_Argc() > 1)
03690 {
03691 char arg[MAX_STRING_CHARS];
03692
03693 trap_Argv( 1, arg, sizeof( arg ) );
03694
03695 if (arg[0])
03696 {
03697 int x = atoi(arg);
03698
03699 if (x >= 0 && x < MAX_CLIENTS)
03700 {
03701 targ = &g_entities[x];
03702 }
03703 }
03704 }
03705
03706 if (targ && targ->inuse && targ->client && ent->s.number != targ->s.number)
03707 {
03708 targ->client->ps.heldByClient = ent->s.number+1;
03709 }
03710 }
03711 else if (Q_stricmp(cmd, "debugIKBeGrabbedBy") == 0)
03712 {
03713 gentity_t *targ = NULL;
03714
03715 if (trap_Argc() > 1)
03716 {
03717 char arg[MAX_STRING_CHARS];
03718
03719 trap_Argv( 1, arg, sizeof( arg ) );
03720
03721 if (arg[0])
03722 {
03723 int x = atoi(arg);
03724
03725 if (x >= 0 && x < MAX_CLIENTS)
03726 {
03727 targ = &g_entities[x];
03728 }
03729 }
03730 }
03731
03732 if (targ && targ->inuse && targ->client && ent->s.number != targ->s.number)
03733 {
03734 ent->client->ps.heldByClient = targ->s.number+1;
03735 }
03736 }
03737 else if (Q_stricmp(cmd, "debugIKRelease") == 0)
03738 {
03739 gentity_t *targ = NULL;
03740
03741 if (trap_Argc() > 1)
03742 {
03743 char arg[MAX_STRING_CHARS];
03744
03745 trap_Argv( 1, arg, sizeof( arg ) );
03746
03747 if (arg[0])
03748 {
03749 int x = atoi(arg);
03750
03751 if (x >= 0 && x < MAX_CLIENTS)
03752 {
03753 targ = &g_entities[x];
03754 }
03755 }
03756 }
03757
03758 if (targ && targ->inuse && targ->client)
03759 {
03760 targ->client->ps.heldByClient = 0;
03761 }
03762 }
03763 else if (Q_stricmp(cmd, "debugThrow") == 0)
03764 {
03765 trace_t tr;
03766 vec3_t tTo, fwd;
03767
03768 if (ent->client->ps.weaponTime > 0 || ent->client->ps.forceHandExtend != HANDEXTEND_NONE ||
03769 ent->client->ps.groundEntityNum == ENTITYNUM_NONE || ent->health < 1)
03770 {
03771 return;
03772 }
03773
03774 AngleVectors(ent->client->ps.viewangles, fwd, 0, 0);
03775 tTo[0] = ent->client->ps.origin[0] + fwd[0]*32;
03776 tTo[1] = ent->client->ps.origin[1] + fwd[1]*32;
03777 tTo[2] = ent->client->ps.origin[2] + fwd[2]*32;
03778
03779 trap_Trace(&tr, ent->client->ps.origin, 0, 0, tTo, ent->s.number, MASK_PLAYERSOLID);
03780
03781 if (tr.fraction != 1)
03782 {
03783 gentity_t *other = &g_entities[tr.entityNum];
03784
03785 if (other->inuse && other->client && other->client->ps.forceHandExtend == HANDEXTEND_NONE &&
03786 other->client->ps.groundEntityNum != ENTITYNUM_NONE && other->health > 0 &&
03787 (int)ent->client->ps.origin[2] == (int)other->client->ps.origin[2])
03788 {
03789 float pDif = 40.0f;
03790 vec3_t entAngles, entDir;
03791 vec3_t otherAngles, otherDir;
03792 vec3_t intendedOrigin;
03793 vec3_t boltOrg, pBoltOrg;
03794 vec3_t tAngles, vDif;
03795 vec3_t fwd, right;
03796 trace_t tr;
03797 trace_t tr2;
03798
03799 VectorSubtract( other->client->ps.origin, ent->client->ps.origin, otherDir );
03800 VectorCopy( ent->client->ps.viewangles, entAngles );
03801 entAngles[YAW] = vectoyaw( otherDir );
03802 SetClientViewAngle( ent, entAngles );
03803
03804 ent->client->ps.forceHandExtend = HANDEXTEND_PRETHROW;
03805 ent->client->ps.forceHandExtendTime = level.time + 5000;
03806
03807 ent->client->throwingIndex = other->s.number;
03808 ent->client->doingThrow = level.time + 5000;
03809 ent->client->beingThrown = 0;
03810
03811 VectorSubtract( ent->client->ps.origin, other->client->ps.origin, entDir );
03812 VectorCopy( other->client->ps.viewangles, otherAngles );
03813 otherAngles[YAW] = vectoyaw( entDir );
03814 SetClientViewAngle( other, otherAngles );
03815
03816 other->client->ps.forceHandExtend = HANDEXTEND_PRETHROWN;
03817 other->client->ps.forceHandExtendTime = level.time + 5000;
03818
03819 other->client->throwingIndex = ent->s.number;
03820 other->client->beingThrown = level.time + 5000;
03821 other->client->doingThrow = 0;
03822
03823
03824
03825
03826 G_EntitySound( other, CHAN_VOICE, G_SoundIndex("*pain100.wav") );
03827 G_EntitySound( ent, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
03828 G_Sound(other, CHAN_AUTO, G_SoundIndex( "sound/movers/objects/objectHit.wav" ));
03829
03830
03831 VectorClear(tAngles);
03832 tAngles[YAW] = ent->client->ps.viewangles[YAW];
03833 VectorCopy(ent->client->ps.origin, pBoltOrg);
03834 AngleVectors(tAngles, fwd, right, 0);
03835 boltOrg[0] = pBoltOrg[0] + fwd[0]*8 + right[0]*pDif;
03836 boltOrg[1] = pBoltOrg[1] + fwd[1]*8 + right[1]*pDif;
03837 boltOrg[2] = pBoltOrg[2];
03838
03839 VectorSubtract(boltOrg, pBoltOrg, vDif);
03840 VectorNormalize(vDif);
03841
03842 VectorClear(other->client->ps.velocity);
03843 intendedOrigin[0] = pBoltOrg[0] + vDif[0]*pDif;
03844 intendedOrigin[1] = pBoltOrg[1] + vDif[1]*pDif;
03845 intendedOrigin[2] = other->client->ps.origin[2];
03846
03847 trap_Trace(&tr, intendedOrigin, other->r.mins, other->r.maxs, intendedOrigin, other->s.number, other->clipmask);
03848 trap_Trace(&tr2, ent->client->ps.origin, ent->r.mins, ent->r.maxs, intendedOrigin, ent->s.number, CONTENTS_SOLID);
03849
03850 if (tr.fraction == 1.0 && !tr.startsolid && tr2.fraction == 1.0 && !tr2.startsolid)
03851 {
03852 VectorCopy(intendedOrigin, other->client->ps.origin);
03853 }
03854 else
03855 {
03856 vec3_t oppDir;
03857 int strength = 4;
03858
03859 other->client->ps.heldByClient = 0;
03860 other->client->beingThrown = 0;
03861 ent->client->doingThrow = 0;
03862
03863 ent->client->ps.forceHandExtend = HANDEXTEND_NONE;
03864 G_EntitySound( ent, CHAN_VOICE, G_SoundIndex("*pain25.wav") );
03865
03866 other->client->ps.forceHandExtend = HANDEXTEND_NONE;
03867 VectorSubtract(other->client->ps.origin, ent->client->ps.origin, oppDir);
03868 VectorNormalize(oppDir);
03869 other->client->ps.velocity[0] = oppDir[0]*(strength*40);
03870 other->client->ps.velocity[1] = oppDir[1]*(strength*40);
03871 other->client->ps.velocity[2] = 150;
03872
03873 VectorSubtract(ent->client->ps.origin, other->client->ps.origin, oppDir);
03874 VectorNormalize(oppDir);
03875 ent->client->ps.velocity[0] = oppDir[0]*(strength*40);
03876 ent->client->ps.velocity[1] = oppDir[1]*(strength*40);
03877 ent->client->ps.velocity[2] = 150;
03878 }
03879 }
03880 }
03881 }
03882 #endif
03883 #ifdef VM_MEMALLOC_DEBUG
03884 else if (Q_stricmp(cmd, "debugTestAlloc") == 0)
03885 {
03886 char *blah;
03887 int i = 1;
03888 int x;
03889
03890
03891 while (i < 32768)
03892 {
03893 x = 0;
03894
03895 trap_TrueMalloc((void **)&blah, i);
03896 if (!blah)
03897 {
03898 trap_SendServerCommand( -1, va("print \"Failed to alloc at %i!\n\"", i));
03899 break;
03900 }
03901 while (x < i)
03902 {
03903 if (x+1 == i)
03904 {
03905 blah[x] = 0;
03906 }
03907 else
03908 {
03909 blah[x] = 'A';
03910 }
03911 x++;
03912 }
03913 trap_TrueFree((void **)&blah);
03914 if (blah)
03915 {
03916 trap_SendServerCommand( -1, va("print \"Failed to free at %i!\n\"", i));
03917 break;
03918 }
03919
03920 i++;
03921 }
03922
03923 trap_SendServerCommand( -1, "print \"Finished allocation test\n\"");
03924 }
03925 #endif
03926 #ifndef FINAL_BUILD
03927 else if (Q_stricmp(cmd, "debugShipDamage") == 0)
03928 {
03929 char arg[MAX_STRING_CHARS];
03930 char arg2[MAX_STRING_CHARS];
03931 int shipSurf, damageLevel;
03932
03933 trap_Argv( 1, arg, sizeof( arg ) );
03934 trap_Argv( 2, arg2, sizeof( arg2 ) );
03935 shipSurf = SHIPSURF_FRONT+atoi(arg);
03936 damageLevel = atoi(arg2);
03937
03938 G_SetVehDamageFlags( &g_entities[ent->s.m_iVehicleNum], shipSurf, damageLevel );
03939 }
03940 #endif
03941 else
03942 {
03943 if (Q_stricmp(cmd, "addbot") == 0)
03944 {
03945
03946 trap_SendServerCommand( clientNum, va("print \"%s.\n\"", G_GetStringEdString("MP_SVGAME", "ONLY_ADD_BOTS_AS_SERVER")));
03947 }
03948 else
03949 {
03950 trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
03951 }
03952 }
03953 }