00001
00002
00003
00004 #include "g_local.h"
00005 #include "bg_saga.h"
00006
00007
00008 typedef struct teamgame_s {
00009 float last_flag_capture;
00010 int last_capture_team;
00011 flagStatus_t redStatus;
00012 flagStatus_t blueStatus;
00013 flagStatus_t flagStatus;
00014 int redTakenTime;
00015 int blueTakenTime;
00016 } teamgame_t;
00017
00018 teamgame_t teamgame;
00019
00020 void Team_SetFlagStatus( int team, flagStatus_t status );
00021
00022 void Team_InitGame( void ) {
00023 memset(&teamgame, 0, sizeof teamgame);
00024
00025 switch( g_gametype.integer ) {
00026 case GT_CTF:
00027 case GT_CTY:
00028 teamgame.redStatus = teamgame.blueStatus = -1;
00029 Team_SetFlagStatus( TEAM_RED, FLAG_ATBASE );
00030 Team_SetFlagStatus( TEAM_BLUE, FLAG_ATBASE );
00031 break;
00032 default:
00033 break;
00034 }
00035 }
00036
00037 int OtherTeam(int team) {
00038 if (team==TEAM_RED)
00039 return TEAM_BLUE;
00040 else if (team==TEAM_BLUE)
00041 return TEAM_RED;
00042 return team;
00043 }
00044
00045 const char *TeamName(int team) {
00046 if (team==TEAM_RED)
00047 return "RED";
00048 else if (team==TEAM_BLUE)
00049 return "BLUE";
00050 else if (team==TEAM_SPECTATOR)
00051 return "SPECTATOR";
00052 return "FREE";
00053 }
00054
00055 const char *OtherTeamName(int team) {
00056 if (team==TEAM_RED)
00057 return "BLUE";
00058 else if (team==TEAM_BLUE)
00059 return "RED";
00060 else if (team==TEAM_SPECTATOR)
00061 return "SPECTATOR";
00062 return "FREE";
00063 }
00064
00065 const char *TeamColorString(int team) {
00066 if (team==TEAM_RED)
00067 return S_COLOR_RED;
00068 else if (team==TEAM_BLUE)
00069 return S_COLOR_BLUE;
00070 else if (team==TEAM_SPECTATOR)
00071 return S_COLOR_YELLOW;
00072 return S_COLOR_WHITE;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 void PrintCTFMessage(int plIndex, int teamIndex, int ctfMessage)
00101 {
00102 gentity_t *te;
00103
00104 if (plIndex == -1)
00105 {
00106 plIndex = MAX_CLIENTS+1;
00107 }
00108 if (teamIndex == -1)
00109 {
00110 teamIndex = 50;
00111 }
00112
00113 te = G_TempEntity(vec3_origin, EV_CTFMESSAGE);
00114 te->r.svFlags |= SVF_BROADCAST;
00115 te->s.eventParm = ctfMessage;
00116 te->s.trickedentindex = plIndex;
00117 if (ctfMessage == CTFMESSAGE_PLAYER_CAPTURED_FLAG)
00118 {
00119 if (teamIndex == TEAM_RED)
00120 {
00121 te->s.trickedentindex2 = TEAM_BLUE;
00122 }
00123 else
00124 {
00125 te->s.trickedentindex2 = TEAM_RED;
00126 }
00127 }
00128 else
00129 {
00130 te->s.trickedentindex2 = teamIndex;
00131 }
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 void AddTeamScore(vec3_t origin, int team, int score) {
00143 gentity_t *te;
00144
00145 te = G_TempEntity(origin, EV_GLOBAL_TEAM_SOUND );
00146 te->r.svFlags |= SVF_BROADCAST;
00147
00148 if ( team == TEAM_RED ) {
00149 if ( level.teamScores[ TEAM_RED ] + score == level.teamScores[ TEAM_BLUE ] ) {
00150
00151 te->s.eventParm = GTS_TEAMS_ARE_TIED;
00152 }
00153 else if ( level.teamScores[ TEAM_RED ] <= level.teamScores[ TEAM_BLUE ] &&
00154 level.teamScores[ TEAM_RED ] + score > level.teamScores[ TEAM_BLUE ]) {
00155
00156 te->s.eventParm = GTS_REDTEAM_TOOK_LEAD;
00157 }
00158 else {
00159
00160 te->s.eventParm = GTS_REDTEAM_SCORED;
00161 }
00162 }
00163 else {
00164 if ( level.teamScores[ TEAM_BLUE ] + score == level.teamScores[ TEAM_RED ] ) {
00165
00166 te->s.eventParm = GTS_TEAMS_ARE_TIED;
00167 }
00168 else if ( level.teamScores[ TEAM_BLUE ] <= level.teamScores[ TEAM_RED ] &&
00169 level.teamScores[ TEAM_BLUE ] + score > level.teamScores[ TEAM_RED ]) {
00170
00171 te->s.eventParm = GTS_BLUETEAM_TOOK_LEAD;
00172 }
00173 else {
00174
00175 te->s.eventParm = GTS_BLUETEAM_SCORED;
00176 }
00177 }
00178 level.teamScores[ team ] += score;
00179 }
00180
00181
00182
00183
00184
00185
00186 qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 ) {
00187 if ( !ent1->client || !ent2->client ) {
00188 return qfalse;
00189 }
00190
00191 if (g_gametype.integer == GT_POWERDUEL)
00192 {
00193 if (ent1->client->sess.duelTeam == ent2->client->sess.duelTeam)
00194 {
00195 return qtrue;
00196 }
00197
00198 return qfalse;
00199 }
00200
00201 if (g_gametype.integer == GT_SINGLE_PLAYER)
00202 {
00203 qboolean ent1IsBot = qfalse;
00204 qboolean ent2IsBot = qfalse;
00205
00206 if (ent1->r.svFlags & SVF_BOT)
00207 {
00208 ent1IsBot = qtrue;
00209 }
00210 if (ent2->r.svFlags & SVF_BOT)
00211 {
00212 ent2IsBot = qtrue;
00213 }
00214
00215 if ((ent1IsBot && ent2IsBot) || (!ent1IsBot && !ent2IsBot))
00216 {
00217 return qtrue;
00218 }
00219 return qfalse;
00220 }
00221
00222 if ( g_gametype.integer < GT_TEAM ) {
00223 return qfalse;
00224 }
00225
00226 if (ent1->s.eType == ET_NPC &&
00227 ent1->s.NPC_class == CLASS_VEHICLE &&
00228 ent1->client &&
00229 ent1->client->sess.sessionTeam != TEAM_FREE &&
00230 ent2->client &&
00231 ent1->client->sess.sessionTeam == ent2->client->sess.sessionTeam)
00232 {
00233 return qtrue;
00234 }
00235 if (ent2->s.eType == ET_NPC &&
00236 ent2->s.NPC_class == CLASS_VEHICLE &&
00237 ent2->client &&
00238 ent2->client->sess.sessionTeam != TEAM_FREE &&
00239 ent1->client &&
00240 ent2->client->sess.sessionTeam == ent1->client->sess.sessionTeam)
00241 {
00242 return qtrue;
00243 }
00244
00245 if (ent1->client->sess.sessionTeam == TEAM_FREE &&
00246 ent2->client->sess.sessionTeam == TEAM_FREE &&
00247 ent1->s.eType == ET_NPC &&
00248 ent2->s.eType == ET_NPC)
00249 {
00250 return qfalse;
00251 }
00252
00253 if (ent1->s.eType == ET_NPC && ent2->s.eType == ET_PLAYER)
00254 {
00255 return qfalse;
00256 }
00257 else if (ent1->s.eType == ET_PLAYER && ent2->s.eType == ET_NPC)
00258 {
00259 return qfalse;
00260 }
00261
00262 if ( ent1->client->sess.sessionTeam == ent2->client->sess.sessionTeam ) {
00263 return qtrue;
00264 }
00265
00266 return qfalse;
00267 }
00268
00269
00270 static char ctfFlagStatusRemap[] = { '0', '1', '*', '*', '2' };
00271
00272 void Team_SetFlagStatus( int team, flagStatus_t status ) {
00273 qboolean modified = qfalse;
00274
00275 switch( team ) {
00276 case TEAM_RED:
00277 if( teamgame.redStatus != status ) {
00278 teamgame.redStatus = status;
00279 modified = qtrue;
00280 }
00281 break;
00282
00283 case TEAM_BLUE:
00284 if( teamgame.blueStatus != status ) {
00285 teamgame.blueStatus = status;
00286 modified = qtrue;
00287 }
00288 break;
00289
00290 case TEAM_FREE:
00291 if( teamgame.flagStatus != status ) {
00292 teamgame.flagStatus = status;
00293 modified = qtrue;
00294 }
00295 break;
00296 }
00297
00298 if( modified ) {
00299 char st[4];
00300
00301 if( g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY ) {
00302 st[0] = ctfFlagStatusRemap[teamgame.redStatus];
00303 st[1] = ctfFlagStatusRemap[teamgame.blueStatus];
00304 st[2] = 0;
00305 }
00306
00307 trap_SetConfigstring( CS_FLAGSTATUS, st );
00308 }
00309 }
00310
00311 void Team_CheckDroppedItem( gentity_t *dropped ) {
00312 if( dropped->item->giTag == PW_REDFLAG ) {
00313 Team_SetFlagStatus( TEAM_RED, FLAG_DROPPED );
00314 }
00315 else if( dropped->item->giTag == PW_BLUEFLAG ) {
00316 Team_SetFlagStatus( TEAM_BLUE, FLAG_DROPPED );
00317 }
00318 else if( dropped->item->giTag == PW_NEUTRALFLAG ) {
00319 Team_SetFlagStatus( TEAM_FREE, FLAG_DROPPED );
00320 }
00321 }
00322
00323
00324
00325
00326
00327
00328 void Team_ForceGesture(int team) {
00329 int i;
00330 gentity_t *ent;
00331
00332 for (i = 0; i < MAX_CLIENTS; i++) {
00333 ent = &g_entities[i];
00334 if (!ent->inuse)
00335 continue;
00336 if (!ent->client)
00337 continue;
00338 if (ent->client->sess.sessionTeam != team)
00339 continue;
00340
00341 ent->flags |= FL_FORCE_GESTURE;
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 void Team_FragBonuses(gentity_t *targ, gentity_t *inflictor, gentity_t *attacker)
00355 {
00356 int i;
00357 gentity_t *ent;
00358 int flag_pw, enemy_flag_pw;
00359 int otherteam;
00360 int tokens;
00361 gentity_t *flag, *carrier = NULL;
00362 char *c;
00363 vec3_t v1, v2;
00364 int team;
00365
00366
00367 if (!targ->client || !attacker->client || targ == attacker || OnSameTeam(targ, attacker))
00368 return;
00369
00370 team = targ->client->sess.sessionTeam;
00371 otherteam = OtherTeam(targ->client->sess.sessionTeam);
00372 if (otherteam < 0)
00373 return;
00374
00375
00376 if (team == TEAM_RED) {
00377 flag_pw = PW_REDFLAG;
00378 enemy_flag_pw = PW_BLUEFLAG;
00379 } else {
00380 flag_pw = PW_BLUEFLAG;
00381 enemy_flag_pw = PW_REDFLAG;
00382 }
00383
00384
00385 tokens = 0;
00386 if (targ->client->ps.powerups[enemy_flag_pw]) {
00387 attacker->client->pers.teamState.lastfraggedcarrier = level.time;
00388 AddScore(attacker, targ->r.currentOrigin, CTF_FRAG_CARRIER_BONUS);
00389 attacker->client->pers.teamState.fragcarrier++;
00390
00391
00392 PrintCTFMessage(attacker->s.number, team, CTFMESSAGE_FRAGGED_FLAG_CARRIER);
00393
00394
00395
00396 for (i = 0; i < g_maxclients.integer; i++) {
00397 ent = g_entities + i;
00398 if (ent->inuse && ent->client->sess.sessionTeam == otherteam)
00399 ent->client->pers.teamState.lasthurtcarrier = 0;
00400 }
00401 return;
00402 }
00403
00404
00405 if (tokens) {
00406 attacker->client->pers.teamState.lastfraggedcarrier = level.time;
00407 AddScore(attacker, targ->r.currentOrigin, CTF_FRAG_CARRIER_BONUS * tokens * tokens);
00408 attacker->client->pers.teamState.fragcarrier++;
00409
00410
00411
00412
00413
00414 for (i = 0; i < g_maxclients.integer; i++) {
00415 ent = g_entities + i;
00416 if (ent->inuse && ent->client->sess.sessionTeam == otherteam)
00417 ent->client->pers.teamState.lasthurtcarrier = 0;
00418 }
00419 return;
00420 }
00421
00422 if (targ->client->pers.teamState.lasthurtcarrier &&
00423 level.time - targ->client->pers.teamState.lasthurtcarrier < CTF_CARRIER_DANGER_PROTECT_TIMEOUT &&
00424 !attacker->client->ps.powerups[flag_pw]) {
00425
00426
00427 AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_DANGER_PROTECT_BONUS);
00428
00429 attacker->client->pers.teamState.carrierdefense++;
00430 targ->client->pers.teamState.lasthurtcarrier = 0;
00431
00432 attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00433 team = attacker->client->sess.sessionTeam;
00434 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00435
00436 return;
00437 }
00438
00439 if (targ->client->pers.teamState.lasthurtcarrier &&
00440 level.time - targ->client->pers.teamState.lasthurtcarrier < CTF_CARRIER_DANGER_PROTECT_TIMEOUT) {
00441
00442 AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_DANGER_PROTECT_BONUS);
00443
00444 attacker->client->pers.teamState.carrierdefense++;
00445 targ->client->pers.teamState.lasthurtcarrier = 0;
00446
00447 attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00448 team = attacker->client->sess.sessionTeam;
00449 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00450
00451 return;
00452 }
00453
00454
00455
00456
00457
00458
00459 switch (attacker->client->sess.sessionTeam) {
00460 case TEAM_RED:
00461 c = "team_CTF_redflag";
00462 break;
00463 case TEAM_BLUE:
00464 c = "team_CTF_blueflag";
00465 break;
00466 default:
00467 return;
00468 }
00469
00470 for (i = 0; i < g_maxclients.integer; i++) {
00471 carrier = g_entities + i;
00472 if (carrier->inuse && carrier->client->ps.powerups[flag_pw])
00473 break;
00474 carrier = NULL;
00475 }
00476 flag = NULL;
00477 while ((flag = G_Find (flag, FOFS(classname), c)) != NULL) {
00478 if (!(flag->flags & FL_DROPPED_ITEM))
00479 break;
00480 }
00481
00482 if (!flag)
00483 return;
00484
00485
00486
00487
00488 VectorSubtract(targ->r.currentOrigin, flag->r.currentOrigin, v1);
00489 VectorSubtract(attacker->r.currentOrigin, flag->r.currentOrigin, v2);
00490
00491 if ( ( ( VectorLength(v1) < CTF_TARGET_PROTECT_RADIUS &&
00492 trap_InPVS(flag->r.currentOrigin, targ->r.currentOrigin ) ) ||
00493 ( VectorLength(v2) < CTF_TARGET_PROTECT_RADIUS &&
00494 trap_InPVS(flag->r.currentOrigin, attacker->r.currentOrigin ) ) ) &&
00495 attacker->client->sess.sessionTeam != targ->client->sess.sessionTeam) {
00496
00497
00498 AddScore(attacker, targ->r.currentOrigin, CTF_FLAG_DEFENSE_BONUS);
00499 attacker->client->pers.teamState.basedefense++;
00500
00501 attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00502 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00503
00504 return;
00505 }
00506
00507 if (carrier && carrier != attacker) {
00508 VectorSubtract(targ->r.currentOrigin, carrier->r.currentOrigin, v1);
00509 VectorSubtract(attacker->r.currentOrigin, carrier->r.currentOrigin, v1);
00510
00511 if ( ( ( VectorLength(v1) < CTF_ATTACKER_PROTECT_RADIUS &&
00512 trap_InPVS(carrier->r.currentOrigin, targ->r.currentOrigin ) ) ||
00513 ( VectorLength(v2) < CTF_ATTACKER_PROTECT_RADIUS &&
00514 trap_InPVS(carrier->r.currentOrigin, attacker->r.currentOrigin ) ) ) &&
00515 attacker->client->sess.sessionTeam != targ->client->sess.sessionTeam) {
00516 AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_PROTECT_BONUS);
00517 attacker->client->pers.teamState.carrierdefense++;
00518
00519 attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00520 attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00521
00522 return;
00523 }
00524 }
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 void Team_CheckHurtCarrier(gentity_t *targ, gentity_t *attacker)
00536 {
00537 int flag_pw;
00538
00539 if (!targ->client || !attacker->client)
00540 return;
00541
00542 if (targ->client->sess.sessionTeam == TEAM_RED)
00543 flag_pw = PW_BLUEFLAG;
00544 else
00545 flag_pw = PW_REDFLAG;
00546
00547
00548 if (targ->client->ps.powerups[flag_pw] &&
00549 targ->client->sess.sessionTeam != attacker->client->sess.sessionTeam)
00550 attacker->client->pers.teamState.lasthurtcarrier = level.time;
00551
00552
00553 if (targ->client->ps.generic1 &&
00554 targ->client->sess.sessionTeam != attacker->client->sess.sessionTeam)
00555 attacker->client->pers.teamState.lasthurtcarrier = level.time;
00556 }
00557
00558
00559 gentity_t *Team_ResetFlag( int team ) {
00560 char *c;
00561 gentity_t *ent, *rent = NULL;
00562
00563 switch (team) {
00564 case TEAM_RED:
00565 c = "team_CTF_redflag";
00566 break;
00567 case TEAM_BLUE:
00568 c = "team_CTF_blueflag";
00569 break;
00570 case TEAM_FREE:
00571 c = "team_CTF_neutralflag";
00572 break;
00573 default:
00574 return NULL;
00575 }
00576
00577 ent = NULL;
00578 while ((ent = G_Find (ent, FOFS(classname), c)) != NULL) {
00579 if (ent->flags & FL_DROPPED_ITEM)
00580 G_FreeEntity(ent);
00581 else {
00582 rent = ent;
00583 RespawnItem(ent);
00584 }
00585 }
00586
00587 Team_SetFlagStatus( team, FLAG_ATBASE );
00588
00589 return rent;
00590 }
00591
00592 void Team_ResetFlags( void ) {
00593 if( g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY ) {
00594 Team_ResetFlag( TEAM_RED );
00595 Team_ResetFlag( TEAM_BLUE );
00596 }
00597 }
00598
00599 void Team_ReturnFlagSound( gentity_t *ent, int team ) {
00600 gentity_t *te;
00601
00602 if (ent == NULL) {
00603 G_Printf ("Warning: NULL passed to Team_ReturnFlagSound\n");
00604 return;
00605 }
00606
00607 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_TEAM_SOUND );
00608 if( team == TEAM_BLUE ) {
00609 te->s.eventParm = GTS_RED_RETURN;
00610 }
00611 else {
00612 te->s.eventParm = GTS_BLUE_RETURN;
00613 }
00614 te->r.svFlags |= SVF_BROADCAST;
00615 }
00616
00617 void Team_TakeFlagSound( gentity_t *ent, int team ) {
00618 gentity_t *te;
00619
00620 if (ent == NULL) {
00621 G_Printf ("Warning: NULL passed to Team_TakeFlagSound\n");
00622 return;
00623 }
00624
00625
00626
00627 switch(team) {
00628 case TEAM_RED:
00629 if( teamgame.blueStatus != FLAG_ATBASE ) {
00630 if (teamgame.blueTakenTime > level.time - 10000)
00631 return;
00632 }
00633 teamgame.blueTakenTime = level.time;
00634 break;
00635
00636 case TEAM_BLUE:
00637 if( teamgame.redStatus != FLAG_ATBASE ) {
00638 if (teamgame.redTakenTime > level.time - 10000)
00639 return;
00640 }
00641 teamgame.redTakenTime = level.time;
00642 break;
00643 }
00644
00645 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_TEAM_SOUND );
00646 if( team == TEAM_BLUE ) {
00647 te->s.eventParm = GTS_RED_TAKEN;
00648 }
00649 else {
00650 te->s.eventParm = GTS_BLUE_TAKEN;
00651 }
00652 te->r.svFlags |= SVF_BROADCAST;
00653 }
00654
00655 void Team_CaptureFlagSound( gentity_t *ent, int team ) {
00656 gentity_t *te;
00657
00658 if (ent == NULL) {
00659 G_Printf ("Warning: NULL passed to Team_CaptureFlagSound\n");
00660 return;
00661 }
00662
00663 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_TEAM_SOUND );
00664 if( team == TEAM_BLUE ) {
00665 te->s.eventParm = GTS_BLUE_CAPTURE;
00666 }
00667 else {
00668 te->s.eventParm = GTS_RED_CAPTURE;
00669 }
00670 te->r.svFlags |= SVF_BROADCAST;
00671 }
00672
00673 void Team_ReturnFlag( int team ) {
00674 Team_ReturnFlagSound(Team_ResetFlag(team), team);
00675 if( team == TEAM_FREE ) {
00676
00677 }
00678 else {
00679
00680 PrintCTFMessage(-1, team, CTFMESSAGE_FLAG_RETURNED);
00681 }
00682 }
00683
00684 void Team_FreeEntity( gentity_t *ent ) {
00685 if( ent->item->giTag == PW_REDFLAG ) {
00686 Team_ReturnFlag( TEAM_RED );
00687 }
00688 else if( ent->item->giTag == PW_BLUEFLAG ) {
00689 Team_ReturnFlag( TEAM_BLUE );
00690 }
00691 else if( ent->item->giTag == PW_NEUTRALFLAG ) {
00692 Team_ReturnFlag( TEAM_FREE );
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 void Team_DroppedFlagThink(gentity_t *ent) {
00706 int team = TEAM_FREE;
00707
00708 if( ent->item->giTag == PW_REDFLAG ) {
00709 team = TEAM_RED;
00710 }
00711 else if( ent->item->giTag == PW_BLUEFLAG ) {
00712 team = TEAM_BLUE;
00713 }
00714 else if( ent->item->giTag == PW_NEUTRALFLAG ) {
00715 team = TEAM_FREE;
00716 }
00717
00718 Team_ReturnFlagSound( Team_ResetFlag( team ), team );
00719
00720 }
00721
00722
00723
00724
00725
00726
00727
00728 int Team_TouchOurFlag( gentity_t *ent, gentity_t *other, int team ) {
00729 int i;
00730 gentity_t *player;
00731 gclient_t *cl = other->client;
00732 int enemy_flag;
00733
00734 if (cl->sess.sessionTeam == TEAM_RED) {
00735 enemy_flag = PW_BLUEFLAG;
00736 } else {
00737 enemy_flag = PW_REDFLAG;
00738 }
00739
00740 if ( ent->flags & FL_DROPPED_ITEM ) {
00741
00742
00743
00744 PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_RETURNED_FLAG);
00745
00746 AddScore(other, ent->r.currentOrigin, CTF_RECOVERY_BONUS);
00747 other->client->pers.teamState.flagrecovery++;
00748 other->client->pers.teamState.lastreturnedflag = level.time;
00749
00750 Team_ReturnFlagSound(Team_ResetFlag(team), team);
00751 return 0;
00752 }
00753
00754
00755
00756 if (!cl->ps.powerups[enemy_flag])
00757 return 0;
00758
00759 PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_CAPTURED_FLAG);
00760
00761 cl->ps.powerups[enemy_flag] = 0;
00762
00763 teamgame.last_flag_capture = level.time;
00764 teamgame.last_capture_team = team;
00765
00766
00767 AddTeamScore(ent->s.pos.trBase, other->client->sess.sessionTeam, 1);
00768
00769
00770
00771 other->client->pers.teamState.captures++;
00772 other->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00773 other->client->ps.persistant[PERS_CAPTURES]++;
00774
00775
00776 AddScore(other, ent->r.currentOrigin, CTF_CAPTURE_BONUS);
00777
00778 Team_CaptureFlagSound( ent, team );
00779
00780
00781 for (i = 0; i < g_maxclients.integer; i++) {
00782 player = &g_entities[i];
00783 if (!player->inuse)
00784 continue;
00785
00786 if (player->client->sess.sessionTeam !=
00787 cl->sess.sessionTeam) {
00788 player->client->pers.teamState.lasthurtcarrier = -5;
00789 } else if (player->client->sess.sessionTeam ==
00790 cl->sess.sessionTeam) {
00791 if (player != other)
00792 AddScore(player, ent->r.currentOrigin, CTF_TEAM_BONUS);
00793
00794 if (player->client->pers.teamState.lastreturnedflag +
00795 CTF_RETURN_FLAG_ASSIST_TIMEOUT > level.time) {
00796 AddScore (player, ent->r.currentOrigin, CTF_RETURN_FLAG_ASSIST_BONUS);
00797 other->client->pers.teamState.assists++;
00798
00799 player->client->ps.persistant[PERS_ASSIST_COUNT]++;
00800 player->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00801
00802 } else if (player->client->pers.teamState.lastfraggedcarrier +
00803 CTF_FRAG_CARRIER_ASSIST_TIMEOUT > level.time) {
00804 AddScore(player, ent->r.currentOrigin, CTF_FRAG_CARRIER_ASSIST_BONUS);
00805 other->client->pers.teamState.assists++;
00806 player->client->ps.persistant[PERS_ASSIST_COUNT]++;
00807 player->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00808 }
00809 }
00810 }
00811 Team_ResetFlags();
00812
00813 CalculateRanks();
00814
00815 return 0;
00816 }
00817
00818 int Team_TouchEnemyFlag( gentity_t *ent, gentity_t *other, int team ) {
00819 gclient_t *cl = other->client;
00820
00821
00822
00823 PrintCTFMessage(other->s.number, team, CTFMESSAGE_PLAYER_GOT_FLAG);
00824
00825 if (team == TEAM_RED)
00826 cl->ps.powerups[PW_REDFLAG] = INT_MAX;
00827 else
00828 cl->ps.powerups[PW_BLUEFLAG] = INT_MAX;
00829
00830 Team_SetFlagStatus( team, FLAG_TAKEN );
00831
00832 AddScore(other, ent->r.currentOrigin, CTF_FLAG_BONUS);
00833 cl->pers.teamState.flagsince = level.time;
00834 Team_TakeFlagSound( ent, team );
00835
00836 return -1;
00837 }
00838
00839 int Pickup_Team( gentity_t *ent, gentity_t *other ) {
00840 int team;
00841 gclient_t *cl = other->client;
00842
00843
00844 if( strcmp(ent->classname, "team_CTF_redflag") == 0 ) {
00845 team = TEAM_RED;
00846 }
00847 else if( strcmp(ent->classname, "team_CTF_blueflag") == 0 ) {
00848 team = TEAM_BLUE;
00849 }
00850 else if( strcmp(ent->classname, "team_CTF_neutralflag") == 0 ) {
00851 team = TEAM_FREE;
00852 }
00853 else {
00854
00855 return 0;
00856 }
00857
00858 if( team == cl->sess.sessionTeam) {
00859 return Team_TouchOurFlag( ent, other, team );
00860 }
00861 return Team_TouchEnemyFlag( ent, other, team );
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871 gentity_t *Team_GetLocation(gentity_t *ent)
00872 {
00873 gentity_t *eloc, *best;
00874 float bestlen, len;
00875 vec3_t origin;
00876
00877 best = NULL;
00878 bestlen = 3*8192.0*8192.0;
00879
00880 VectorCopy( ent->r.currentOrigin, origin );
00881
00882 for (eloc = level.locationHead; eloc; eloc = eloc->nextTrain) {
00883 len = ( origin[0] - eloc->r.currentOrigin[0] ) * ( origin[0] - eloc->r.currentOrigin[0] )
00884 + ( origin[1] - eloc->r.currentOrigin[1] ) * ( origin[1] - eloc->r.currentOrigin[1] )
00885 + ( origin[2] - eloc->r.currentOrigin[2] ) * ( origin[2] - eloc->r.currentOrigin[2] );
00886
00887 if ( len > bestlen ) {
00888 continue;
00889 }
00890
00891 if ( !trap_InPVS( origin, eloc->r.currentOrigin ) ) {
00892 continue;
00893 }
00894
00895 bestlen = len;
00896 best = eloc;
00897 }
00898
00899 return best;
00900 }
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen)
00911 {
00912 gentity_t *best;
00913
00914 best = Team_GetLocation( ent );
00915
00916 if (!best)
00917 return qfalse;
00918
00919 if (best->count) {
00920 if (best->count < 0)
00921 best->count = 0;
00922 if (best->count > 7)
00923 best->count = 7;
00924 Com_sprintf(loc, loclen, "%c%c%s" S_COLOR_WHITE, Q_COLOR_ESCAPE, best->count + '0', best->message );
00925 } else
00926 Com_sprintf(loc, loclen, "%s", best->message);
00927
00928 return qtrue;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 #define MAX_TEAM_SPAWN_POINTS 32
00942 gentity_t *SelectRandomTeamSpawnPoint( int teamstate, team_t team, int siegeClass ) {
00943 gentity_t *spot;
00944 int count;
00945 int selection;
00946 gentity_t *spots[MAX_TEAM_SPAWN_POINTS];
00947 char *classname;
00948 qboolean mustBeEnabled = qfalse;
00949
00950 if (g_gametype.integer == GT_SIEGE)
00951 {
00952 if (team == SIEGETEAM_TEAM1)
00953 {
00954 classname = "info_player_siegeteam1";
00955 }
00956 else
00957 {
00958 classname = "info_player_siegeteam2";
00959 }
00960
00961 mustBeEnabled = qtrue;
00962 }
00963 else
00964 {
00965 if (teamstate == TEAM_BEGIN) {
00966 if (team == TEAM_RED)
00967 classname = "team_CTF_redplayer";
00968 else if (team == TEAM_BLUE)
00969 classname = "team_CTF_blueplayer";
00970 else
00971 return NULL;
00972 } else {
00973 if (team == TEAM_RED)
00974 classname = "team_CTF_redspawn";
00975 else if (team == TEAM_BLUE)
00976 classname = "team_CTF_bluespawn";
00977 else
00978 return NULL;
00979 }
00980 }
00981 count = 0;
00982
00983 spot = NULL;
00984
00985 while ((spot = G_Find (spot, FOFS(classname), classname)) != NULL) {
00986 if ( SpotWouldTelefrag( spot ) ) {
00987 continue;
00988 }
00989
00990 if (mustBeEnabled && !spot->genericValue1)
00991 {
00992 continue;
00993 }
00994
00995 spots[ count ] = spot;
00996 if (++count == MAX_TEAM_SPAWN_POINTS)
00997 break;
00998 }
00999
01000 if ( !count ) {
01001 return G_Find( NULL, FOFS(classname), classname);
01002 }
01003
01004 if (g_gametype.integer == GT_SIEGE && siegeClass >= 0 &&
01005 bgSiegeClasses[siegeClass].name[0])
01006 {
01007 gentity_t *classSpots[MAX_TEAM_SPAWN_POINTS];
01008 int classCount = 0;
01009 int i = 0;
01010
01011 while (i < count)
01012 {
01013 if (spots[i] && spots[i]->idealclass && spots[i]->idealclass[0] &&
01014 !Q_stricmp(spots[i]->idealclass, bgSiegeClasses[siegeClass].name))
01015 {
01016 classSpots[classCount] = spots[i];
01017 classCount++;
01018 }
01019 i++;
01020 }
01021
01022 if (classCount > 0)
01023 {
01024 selection = rand() % classCount;
01025 return spots[ selection ];
01026 }
01027 }
01028
01029 selection = rand() % count;
01030 return spots[ selection ];
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040 gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles ) {
01041 gentity_t *spot;
01042
01043 spot = SelectRandomTeamSpawnPoint ( teamstate, team, -1 );
01044
01045 if (!spot) {
01046 return SelectSpawnPoint( vec3_origin, origin, angles, team );
01047 }
01048
01049 VectorCopy (spot->s.origin, origin);
01050 origin[2] += 9;
01051 VectorCopy (spot->s.angles, angles);
01052
01053 return spot;
01054 }
01055
01056
01057
01058
01059
01060
01061
01062 gentity_t *SelectSiegeSpawnPoint ( int siegeClass, team_t team, int teamstate, vec3_t origin, vec3_t angles ) {
01063 gentity_t *spot;
01064
01065 spot = SelectRandomTeamSpawnPoint ( teamstate, team, siegeClass );
01066
01067 if (!spot) {
01068 return SelectSpawnPoint( vec3_origin, origin, angles, team );
01069 }
01070
01071 VectorCopy (spot->s.origin, origin);
01072 origin[2] += 9;
01073 VectorCopy (spot->s.angles, angles);
01074
01075 return spot;
01076 }
01077
01078
01079
01080 static int QDECL SortClients( const void *a, const void *b ) {
01081 return *(int *)a - *(int *)b;
01082 }
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 void TeamplayInfoMessage( gentity_t *ent ) {
01095 char entry[1024];
01096 char string[8192];
01097 int stringlength;
01098 int i, j;
01099 gentity_t *player;
01100 int cnt;
01101 int h, a;
01102 int clients[TEAM_MAXOVERLAY];
01103
01104 if ( ! ent->client->pers.teamInfo )
01105 return;
01106
01107
01108
01109
01110 for (i = 0, cnt = 0; i < g_maxclients.integer && cnt < TEAM_MAXOVERLAY; i++) {
01111 player = g_entities + level.sortedClients[i];
01112 if (player->inuse && player->client->sess.sessionTeam ==
01113 ent->client->sess.sessionTeam ) {
01114 clients[cnt++] = level.sortedClients[i];
01115 }
01116 }
01117
01118
01119 qsort( clients, cnt, sizeof( clients[0] ), SortClients );
01120
01121
01122 string[0] = 0;
01123 stringlength = 0;
01124
01125 for (i = 0, cnt = 0; i < g_maxclients.integer && cnt < TEAM_MAXOVERLAY; i++) {
01126 player = g_entities + i;
01127 if (player->inuse && player->client->sess.sessionTeam ==
01128 ent->client->sess.sessionTeam ) {
01129
01130 h = player->client->ps.stats[STAT_HEALTH];
01131 a = player->client->ps.stats[STAT_ARMOR];
01132 if (h < 0) h = 0;
01133 if (a < 0) a = 0;
01134
01135 Com_sprintf (entry, sizeof(entry),
01136 " %i %i %i %i %i %i",
01137
01138 i, player->client->pers.teamState.location, h, a,
01139 player->client->ps.weapon, player->