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

g_team.c File Reference

#include "g_local.h"

Include dependency graph for g_team.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  teamgame_s

Defines

#define MAX_TEAM_SPAWN_POINTS   32

Typedefs

typedef teamgame_s teamgame_t

Functions

void AddTeamScore (vec3_t origin, int team, int score)
void CheckTeamStatus (void)
qboolean OnSameTeam (gentity_t *ent1, gentity_t *ent2)
int OtherTeam (int team)
const char * OtherTeamName (int team)
int Pickup_Team (gentity_t *ent, gentity_t *other)
void QDECL PrintMsg (gentity_t *ent, const char *fmt,...)
gentity_tSelectCTFSpawnPoint (team_t team, int teamstate, vec3_t origin, vec3_t angles)
gentity_tSelectRandomTeamSpawnPoint (int teamstate, team_t team)
int QDECL SortClients (const void *a, const void *b)
void SP_team_CTF_blueplayer (gentity_t *ent)
void SP_team_CTF_bluespawn (gentity_t *ent)
void SP_team_CTF_redplayer (gentity_t *ent)
void SP_team_CTF_redspawn (gentity_t *ent)
void Team_CaptureFlagSound (gentity_t *ent, int team)
void Team_CheckDroppedItem (gentity_t *dropped)
void Team_CheckHurtCarrier (gentity_t *targ, gentity_t *attacker)
void Team_DroppedFlagThink (gentity_t *ent)
void Team_ForceGesture (int team)
void Team_FragBonuses (gentity_t *targ, gentity_t *inflictor, gentity_t *attacker)
void Team_FreeEntity (gentity_t *ent)
gentity_tTeam_GetLocation (gentity_t *ent)
qboolean Team_GetLocationMsg (gentity_t *ent, char *loc, int loclen)
void Team_InitGame (void)
gentity_tTeam_ResetFlag (int team)
void Team_ResetFlags (void)
void Team_ReturnFlag (int team)
void Team_ReturnFlagSound (gentity_t *ent, int team)
void Team_SetFlagStatus (int team, flagStatus_t status)
void Team_TakeFlagSound (gentity_t *ent, int team)
int Team_TouchEnemyFlag (gentity_t *ent, gentity_t *other, int team)
int Team_TouchOurFlag (gentity_t *ent, gentity_t *other, int team)
const char * TeamColorString (int team)
const char * TeamName (int team)
void TeamplayInfoMessage (gentity_t *ent)

Variables

char ctfFlagStatusRemap [] = { '0', '1', '*', '*', '2' }
gentity_tneutralObelisk
char oneFlagStatusRemap [] = { '0', '1', '2', '3', '4' }
teamgame_t teamgame


Define Documentation

#define MAX_TEAM_SPAWN_POINTS   32
 

Definition at line 982 of file g_team.c.


Typedef Documentation

typedef struct teamgame_s teamgame_t
 


Function Documentation

void AddTeamScore vec3_t  origin,
int  team,
int  score
 

Definition at line 130 of file g_team.c.

References EV_GLOBAL_TEAM_SOUND, entityState_s::eventParm, G_TempEntity(), gentity_t, level, gentity_s::r, gentity_s::s, entityShared_t::svFlags, and level_locals_t::teamScores.

Referenced by Team_TouchOurFlag().

00130                                                       {
00131     gentity_t   *te;
00132 
00133     te = G_TempEntity(origin, EV_GLOBAL_TEAM_SOUND );
00134     te->r.svFlags |= SVF_BROADCAST;
00135 
00136     if ( team == TEAM_RED ) {
00137         if ( level.teamScores[ TEAM_RED ] + score == level.teamScores[ TEAM_BLUE ] ) {
00138             //teams are tied sound
00139             te->s.eventParm = GTS_TEAMS_ARE_TIED;
00140         }
00141         else if ( level.teamScores[ TEAM_RED ] <= level.teamScores[ TEAM_BLUE ] &&
00142                     level.teamScores[ TEAM_RED ] + score > level.teamScores[ TEAM_BLUE ]) {
00143             // red took the lead sound
00144             te->s.eventParm = GTS_REDTEAM_TOOK_LEAD;
00145         }
00146         else {
00147             // red scored sound
00148             te->s.eventParm = GTS_REDTEAM_SCORED;
00149         }
00150     }
00151     else {
00152         if ( level.teamScores[ TEAM_BLUE ] + score == level.teamScores[ TEAM_RED ] ) {
00153             //teams are tied sound
00154             te->s.eventParm = GTS_TEAMS_ARE_TIED;
00155         }
00156         else if ( level.teamScores[ TEAM_BLUE ] <= level.teamScores[ TEAM_RED ] &&
00157                     level.teamScores[ TEAM_BLUE ] + score > level.teamScores[ TEAM_RED ]) {
00158             // blue took the lead sound
00159             te->s.eventParm = GTS_BLUETEAM_TOOK_LEAD;
00160         }
00161         else {
00162             // blue scored sound
00163             te->s.eventParm = GTS_BLUETEAM_SCORED;
00164         }
00165     }
00166     level.teamScores[ team ] += score;
00167 }

Here is the call graph for this function:

void CheckTeamStatus void   ) 
 

Definition at line 1123 of file g_team.c.

References gentity_s::client, clientPersistant_t::connected, g_entities, g_maxclients, gentity_t, gentity_s::health, i, vmCvar_t::integer, gentity_s::inuse, level_locals_t::lastTeamLocationTime, level, playerTeamState_t::location, gclient_s::pers, gclient_s::sess, clientSession_t::sessionTeam, Team_GetLocation(), TEAM_RED, TeamplayInfoMessage(), clientPersistant_t::teamState, and level_locals_t::time.

Referenced by G_RunFrame().

01123                            {
01124     int i;
01125     gentity_t *loc, *ent;
01126 
01127     if (level.time - level.lastTeamLocationTime > TEAM_LOCATION_UPDATE_TIME) {
01128 
01129         level.lastTeamLocationTime = level.time;
01130 
01131         for (i = 0; i < g_maxclients.integer; i++) {
01132             ent = g_entities + i;
01133 
01134             if ( ent->client->pers.connected != CON_CONNECTED ) {
01135                 continue;
01136             }
01137 
01138             if (ent->inuse && (ent->client->sess.sessionTeam == TEAM_RED || ent->client->sess.sessionTeam == TEAM_BLUE)) {
01139                 loc = Team_GetLocation( ent );
01140                 if (loc)
01141                     ent->client->pers.teamState.location = loc->health;
01142                 else
01143                     ent->client->pers.teamState.location = 0;
01144             }
01145         }
01146 
01147         for (i = 0; i < g_maxclients.integer; i++) {
01148             ent = g_entities + i;
01149 
01150             if ( ent->client->pers.connected != CON_CONNECTED ) {
01151                 continue;
01152             }
01153 
01154             if (ent->inuse && (ent->client->sess.sessionTeam == TEAM_RED || ent->client->sess.sessionTeam == TEAM_BLUE)) {
01155                 TeamplayInfoMessage( ent );
01156             }
01157         }
01158     }
01159 }

Here is the call graph for this function:

qboolean OnSameTeam gentity_t ent1,
gentity_t ent2
 

Definition at line 174 of file g_team.c.

References gentity_s::client, g_gametype, gentity_t, qboolean, gclient_s::sess, and clientSession_t::sessionTeam.

Referenced by G_Damage(), G_RankDamage(), G_SayTo(), G_VoiceTo(), LogAccuracyHit(), player_die(), and Team_FragBonuses().

00174                                                         {
00175     if ( !ent1->client || !ent2->client ) {
00176         return qfalse;
00177     }
00178 
00179     if ( g_gametype.integer < GT_TEAM ) {
00180         return qfalse;
00181     }
00182 
00183     if ( ent1->client->sess.sessionTeam == ent2->client->sess.sessionTeam ) {
00184         return qtrue;
00185     }
00186 
00187     return qfalse;
00188 }

int OtherTeam int  team  ) 
 

Definition at line 65 of file g_team.c.

Referenced by Team_FragBonuses(), and Team_TouchOurFlag().

00065                         {
00066     if (team==TEAM_RED)
00067         return TEAM_BLUE;
00068     else if (team==TEAM_BLUE)
00069         return TEAM_RED;
00070     return team;
00071 }

const char* OtherTeamName int  team  ) 
 

Definition at line 83 of file g_team.c.

00083                                     {
00084     if (team==TEAM_RED)
00085         return "BLUE";
00086     else if (team==TEAM_BLUE)
00087         return "RED";
00088     else if (team==TEAM_SPECTATOR)
00089         return "SPECTATOR";
00090     return "FREE";
00091 }

int Pickup_Team gentity_t ent,
gentity_t other
 

Definition at line 851 of file g_team.c.

References cl, gentity_s::classname, gentity_s::client, G_FreeEntity(), g_gametype, gclient_t, gentity_t, PrintMsg(), gentity_s::spawnflags, strcmp(), Team_TouchEnemyFlag(), and Team_TouchOurFlag().

Referenced by Touch_Item().

00851                                                     {
00852     int team;
00853     gclient_t *cl = other->client;
00854 
00855 #ifdef MISSIONPACK
00856     if( g_gametype.integer == GT_OBELISK ) {
00857         // there are no team items that can be picked up in obelisk
00858         G_FreeEntity( ent );
00859         return 0;
00860     }
00861 
00862     if( g_gametype.integer == GT_HARVESTER ) {
00863         // the only team items that can be picked up in harvester are the cubes
00864         if( ent->spawnflags != cl->sess.sessionTeam ) {
00865             cl->ps.generic1 += 1;
00866         }
00867         G_FreeEntity( ent );
00868         return 0;
00869     }
00870 #endif
00871     // figure out what team this flag is
00872     if( strcmp(ent->classname, "team_CTF_redflag") == 0 ) {
00873         team = TEAM_RED;
00874     }
00875     else if( strcmp(ent->classname, "team_CTF_blueflag") == 0 ) {
00876         team = TEAM_BLUE;
00877     }
00878 #ifdef MISSIONPACK
00879     else if( strcmp(ent->classname, "team_CTF_neutralflag") == 0  ) {
00880         team = TEAM_FREE;
00881     }
00882 #endif
00883     else {
00884         PrintMsg ( other, "Don't know what team the flag is on.\n");
00885         return 0;
00886     }
00887 #ifdef MISSIONPACK
00888     if( g_gametype.integer == GT_1FCTF ) {
00889         if( team == TEAM_FREE ) {
00890             return Team_TouchEnemyFlag( ent, other, cl->sess.sessionTeam );
00891         }
00892         if( team != cl->sess.sessionTeam) {
00893             return Team_TouchOurFlag( ent, other, cl->sess.sessionTeam );
00894         }
00895         return 0;
00896     }
00897 #endif
00898     // GT_CTF
00899     if( team == cl->sess.sessionTeam) {
00900         return Team_TouchOurFlag( ent, other, team );
00901     }
00902     return Team_TouchEnemyFlag( ent, other, team );
00903 }

Here is the call graph for this function:

void QDECL PrintMsg gentity_t ent,
const char *  fmt,
  ...
 

Definition at line 104 of file g_team.c.

References g_entities, G_Error(), gentity_t, NULL, p, QDECL, strchr(), trap_SendServerCommand(), va(), va_end, va_list, va_start, and vsprintf().

Referenced by Pickup_Team(), Team_FragBonuses(), Team_ReturnFlag(), Team_TouchEnemyFlag(), and Team_TouchOurFlag().

00104                                                             {
00105     char        msg[1024];
00106     va_list     argptr;
00107     char        *p;
00108     
00109     va_start (argptr,fmt);
00110     if (vsprintf (msg, fmt, argptr) > sizeof(msg)) {
00111         G_Error ( "PrintMsg overrun" );
00112     }
00113     va_end (argptr);
00114 
00115     // double quotes are bad
00116     while ((p = strchr(msg, '"')) != NULL)
00117         *p = '\'';
00118 
00119     trap_SendServerCommand ( ( (ent == NULL) ? -1 : ent-g_entities ), va("print \"%s\"", msg ));
00120 }

Here is the call graph for this function:

gentity_t* SelectCTFSpawnPoint team_t  team,
int  teamstate,
vec3_t  origin,
vec3_t  angles
 

Definition at line 1033 of file g_team.c.

References entityState_s::angles, gentity_t, entityState_s::origin, gentity_s::s, SelectRandomTeamSpawnPoint(), SelectSpawnPoint(), vec3_origin, and VectorCopy.

Referenced by ClientSpawn().

01033                                                                                             {
01034     gentity_t   *spot;
01035 
01036     spot = SelectRandomTeamSpawnPoint ( teamstate, team );
01037 
01038     if (!spot) {
01039         return SelectSpawnPoint( vec3_origin, origin, angles );
01040     }
01041 
01042     VectorCopy (spot->s.origin, origin);
01043     origin[2] += 9;
01044     VectorCopy (spot->s.angles, angles);
01045 
01046     return spot;
01047 }

Here is the call graph for this function:

gentity_t* SelectRandomTeamSpawnPoint int  teamstate,
team_t  team
 

Definition at line 983 of file g_team.c.

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

Referenced by SelectCTFSpawnPoint().

00983                                                                     {
00984     gentity_t   *spot;
00985     int         count;
00986     int         selection;
00987     gentity_t   *spots[MAX_TEAM_SPAWN_POINTS];
00988     char        *classname;
00989 
00990     if (teamstate == TEAM_BEGIN) {
00991         if (team == TEAM_RED)
00992             classname = "team_CTF_redplayer";
00993         else if (team == TEAM_BLUE)
00994             classname = "team_CTF_blueplayer";
00995         else
00996             return NULL;
00997     } else {
00998         if (team == TEAM_RED)
00999             classname = "team_CTF_redspawn";
01000         else if (team == TEAM_BLUE)
01001             classname = "team_CTF_bluespawn";
01002         else
01003             return NULL;
01004     }
01005     count = 0;
01006 
01007     spot = NULL;
01008 
01009     while ((spot = G_Find (spot, FOFS(classname), classname)) != NULL) {
01010         if ( SpotWouldTelefrag( spot ) ) {
01011             continue;
01012         }
01013         spots[ count ] = spot;
01014         if (++count == MAX_TEAM_SPAWN_POINTS)
01015             break;
01016     }
01017 
01018     if ( !count ) { // no spots that won't telefrag
01019         return G_Find( NULL, FOFS(classname), classname);
01020     }
01021 
01022     selection = rand() % count;
01023     return spots[ selection ];
01024 }

Here is the call graph for this function:

int QDECL SortClients const void *  a,
const void *  b
[static]
 

Definition at line 1051 of file g_team.c.

References a, and QDECL.

Referenced by TeamplayInfoMessage().

01051                                                              {
01052     return *(int *)a - *(int *)b;
01053 }

void SP_team_CTF_blueplayer gentity_t ent  ) 
 

Definition at line 1173 of file g_team.c.

References gentity_t.

01173                                               {
01174 }

void SP_team_CTF_bluespawn gentity_t ent  ) 
 

Definition at line 1188 of file g_team.c.

References gentity_t.

01188                                            {
01189 }

void SP_team_CTF_redplayer gentity_t ent  ) 
 

Definition at line 1166 of file g_team.c.

References gentity_t.

01166                                              {
01167 }

void SP_team_CTF_redspawn gentity_t ent  ) 
 

Definition at line 1181 of file g_team.c.

References gentity_t.

01181                                           {
01182 }

void Team_CaptureFlagSound gentity_t ent,
int  team
 

Definition at line 628 of file g_team.c.

References EV_GLOBAL_TEAM_SOUND, entityState_s::eventParm, G_Printf(), G_TempEntity(), gentity_t, entityState_s::pos, gentity_s::r, gentity_s::s, entityShared_t::svFlags, and trajectory_t::trBase.

Referenced by Team_TouchOurFlag().

00628                                                        {
00629     gentity_t   *te;
00630 
00631     if (ent == NULL) {
00632         G_Printf ("Warning:  NULL passed to Team_CaptureFlagSound\n");
00633         return;
00634     }
00635 
00636     te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_TEAM_SOUND );
00637     if( team == TEAM_BLUE ) {
00638         te->s.eventParm = GTS_BLUE_CAPTURE;
00639     }
00640     else {
00641         te->s.eventParm = GTS_RED_CAPTURE;
00642     }
00643     te->r.svFlags |= SVF_BROADCAST;
00644 }

Here is the call graph for this function:

void Team_CheckDroppedItem gentity_t dropped  ) 
 

Definition at line 237 of file g_team.c.

References FLAG_DROPPED, gentity_t, gitem_s::giTag, gentity_s::item, TEAM_BLUE, TEAM_FREE, TEAM_RED, and Team_SetFlagStatus().

Referenced by LaunchItem().

00237                                                  {
00238     if( dropped->item->giTag == PW_REDFLAG ) {
00239         Team_SetFlagStatus( TEAM_RED, FLAG_DROPPED );
00240     }
00241     else if( dropped->item->giTag == PW_BLUEFLAG ) {
00242         Team_SetFlagStatus( TEAM_BLUE, FLAG_DROPPED );
00243     }
00244     else if( dropped->item->giTag == PW_NEUTRALFLAG ) {
00245         Team_SetFlagStatus( TEAM_FREE, FLAG_DROPPED );
00246     }
00247 }

Here is the call graph for this function:

void Team_CheckHurtCarrier gentity_t targ,
gentity_t attacker
 

Definition at line 503 of file g_team.c.

References gentity_s::client, playerState_s::generic1, gentity_t, playerTeamState_t::lasthurtcarrier, level, gclient_s::pers, playerState_s::powerups, gclient_s::ps, gclient_s::sess, clientSession_t::sessionTeam, clientPersistant_t::teamState, and level_locals_t::time.

Referenced by G_Damage().

00504 {
00505     int flag_pw;
00506 
00507     if (!targ->client || !attacker->client)
00508         return;
00509 
00510     if (targ->client->sess.sessionTeam == TEAM_RED)
00511         flag_pw = PW_BLUEFLAG;
00512     else
00513         flag_pw = PW_REDFLAG;
00514 
00515     // flags
00516     if (targ->client->ps.powerups[flag_pw] &&
00517         targ->client->sess.sessionTeam != attacker->client->sess.sessionTeam)
00518         attacker->client->pers.teamState.lasthurtcarrier = level.time;
00519 
00520     // skulls
00521     if (targ->client->ps.generic1 &&
00522         targ->client->sess.sessionTeam != attacker->client->sess.sessionTeam)
00523         attacker->client->pers.teamState.lasthurtcarrier = level.time;
00524 }

void Team_DroppedFlagThink gentity_t ent  ) 
 

Definition at line 677 of file g_team.c.

References gentity_t, gitem_s::giTag, gentity_s::item, Team_ResetFlag(), and Team_ReturnFlagSound().

Referenced by Blocked_Door().

00677                                            {
00678     int     team = TEAM_FREE;
00679 
00680     if( ent->item->giTag == PW_REDFLAG ) {
00681         team = TEAM_RED;
00682     }
00683     else if( ent->item->giTag == PW_BLUEFLAG ) {
00684         team = TEAM_BLUE;
00685     }
00686     else if( ent->item->giTag == PW_NEUTRALFLAG ) {
00687         team = TEAM_FREE;
00688     }
00689 
00690     Team_ReturnFlagSound( Team_ResetFlag( team ), team );
00691     // Reset Flag will delete this entity
00692 }

Here is the call graph for this function:

void Team_ForceGesture int  team  ) 
 

Definition at line 254 of file g_team.c.

References gentity_s::client, gentity_s::flags, g_entities, gentity_t, i, gentity_s::inuse, gclient_s::sess, and clientSession_t::sessionTeam.

Referenced by Team_TouchOurFlag().

00254                                  {
00255     int i;
00256     gentity_t *ent;
00257 
00258     for (i = 0; i < MAX_CLIENTS; i++) {
00259         ent = &g_entities[i];
00260         if (!ent->inuse)
00261             continue;
00262         if (!ent->client)
00263             continue;
00264         if (ent->client->sess.sessionTeam != team)
00265             continue;
00266         //
00267         ent->flags |= FL_FORCE_GESTURE;
00268     }
00269 }

void Team_FragBonuses gentity_t targ,
gentity_t inflictor,
gentity_t attacker
 

Definition at line 280 of file g_team.c.

References AddScore(), playerTeamState_t::basedefense, c, playerTeamState_t::carrierdefense, gentity_s::client, CTF_ATTACKER_PROTECT_RADIUS, CTF_CARRIER_DANGER_PROTECT_BONUS, CTF_CARRIER_DANGER_PROTECT_TIMEOUT, CTF_CARRIER_PROTECT_BONUS, CTF_FLAG_DEFENSE_BONUS, CTF_FRAG_CARRIER_BONUS, CTF_TARGET_PROTECT_RADIUS, entityShared_t::currentOrigin, EF_AWARD_ASSIST, EF_AWARD_DEFEND, EF_AWARD_EXCELLENT, EF_AWARD_GAUNTLET, EF_AWARD_IMPRESSIVE, playerState_s::eFlags, gentity_s::flags, FOFS, playerTeamState_t::fragcarrier, g_entities, G_Find(), g_gametype, g_maxclients, playerState_s::generic1, gentity_t, i, vmCvar_t::integer, gentity_s::inuse, playerTeamState_t::lastfraggedcarrier, playerTeamState_t::lasthurtcarrier, level, clientPersistant_t::netname, NULL, OnSameTeam(), OtherTeam(), gclient_s::pers, playerState_s::persistant, playerState_s::powerups, PrintMsg(), gclient_s::ps, gentity_s::r, gclient_s::rewardTime, S_COLOR_WHITE, gclient_s::sess, clientSession_t::sessionTeam, TEAM_BLUE, TEAM_RED, TeamName(), clientPersistant_t::teamState, level_locals_t::time, trap_InPVS(), v1, v2, vec3_t, VectorLength(), and VectorSubtract.

Referenced by player_die().

00281 {
00282     int i;
00283     gentity_t *ent;
00284     int flag_pw, enemy_flag_pw;
00285     int otherteam;
00286     int tokens;
00287     gentity_t *flag, *carrier = NULL;
00288     char *c;
00289     vec3_t v1, v2;
00290     int team;
00291 
00292     // no bonus for fragging yourself or team mates
00293     if (!targ->client || !attacker->client || targ == attacker || OnSameTeam(targ, attacker))
00294         return;
00295 
00296     team = targ->client->sess.sessionTeam;
00297     otherteam = OtherTeam(targ->client->sess.sessionTeam);
00298     if (otherteam < 0)
00299         return; // whoever died isn't on a team
00300 
00301     // same team, if the flag at base, check to he has the enemy flag
00302     if (team == TEAM_RED) {
00303         flag_pw = PW_REDFLAG;
00304         enemy_flag_pw = PW_BLUEFLAG;
00305     } else {
00306         flag_pw = PW_BLUEFLAG;
00307         enemy_flag_pw = PW_REDFLAG;
00308     }
00309 
00310     if (g_gametype.integer == GT_1FCTF) {
00311         enemy_flag_pw = PW_NEUTRALFLAG;
00312     } 
00313 
00314     // did the attacker frag the flag carrier?
00315     tokens = 0;
00316 #ifdef MISSIONPACK
00317     if( g_gametype.integer == GT_HARVESTER ) {
00318         tokens = targ->client->ps.generic1;
00319     }
00320 #endif
00321     if (targ->client->ps.powerups[enemy_flag_pw]) {
00322         attacker->client->pers.teamState.lastfraggedcarrier = level.time;
00323         AddScore(attacker, targ->r.currentOrigin, CTF_FRAG_CARRIER_BONUS);
00324         attacker->client->pers.teamState.fragcarrier++;
00325         PrintMsg(NULL, "%s" S_COLOR_WHITE " fragged %s's flag carrier!\n",
00326             attacker->client->pers.netname, TeamName(team));
00327 
00328         // the target had the flag, clear the hurt carrier
00329         // field on the other team
00330         for (i = 0; i < g_maxclients.integer; i++) {
00331             ent = g_entities + i;
00332             if (ent->inuse && ent->client->sess.sessionTeam == otherteam)
00333                 ent->client->pers.teamState.lasthurtcarrier = 0;
00334         }
00335         return;
00336     }
00337 
00338     // did the attacker frag a head carrier? other->client->ps.generic1
00339     if (tokens) {
00340         attacker->client->pers.teamState.lastfraggedcarrier = level.time;
00341         AddScore(attacker, targ->r.currentOrigin, CTF_FRAG_CARRIER_BONUS * tokens * tokens);
00342         attacker->client->pers.teamState.fragcarrier++;
00343         PrintMsg(NULL, "%s" S_COLOR_WHITE " fragged %s's skull carrier!\n",
00344             attacker->client->pers.netname, TeamName(team));
00345 
00346         // the target had the flag, clear the hurt carrier
00347         // field on the other team
00348         for (i = 0; i < g_maxclients.integer; i++) {
00349             ent = g_entities + i;
00350             if (ent->inuse && ent->client->sess.sessionTeam == otherteam)
00351                 ent->client->pers.teamState.lasthurtcarrier = 0;
00352         }
00353         return;
00354     }
00355 
00356     if (targ->client->pers.teamState.lasthurtcarrier &&
00357         level.time - targ->client->pers.teamState.lasthurtcarrier < CTF_CARRIER_DANGER_PROTECT_TIMEOUT &&
00358         !attacker->client->ps.powerups[flag_pw]) {
00359         // attacker is on the same team as the flag carrier and
00360         // fragged a guy who hurt our flag carrier
00361         AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_DANGER_PROTECT_BONUS);
00362 
00363         attacker->client->pers.teamState.carrierdefense++;
00364         targ->client->pers.teamState.lasthurtcarrier = 0;
00365 
00366         attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00367         team = attacker->client->sess.sessionTeam;
00368         // add the sprite over the player's head
00369         attacker->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
00370         attacker->client->ps.eFlags |= EF_AWARD_DEFEND;
00371         attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00372 
00373         return;
00374     }
00375 
00376     if (targ->client->pers.teamState.lasthurtcarrier &&
00377         level.time - targ->client->pers.teamState.lasthurtcarrier < CTF_CARRIER_DANGER_PROTECT_TIMEOUT) {
00378         // attacker is on the same team as the skull carrier and
00379         AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_DANGER_PROTECT_BONUS);
00380 
00381         attacker->client->pers.teamState.carrierdefense++;
00382         targ->client->pers.teamState.lasthurtcarrier = 0;
00383 
00384         attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00385         team = attacker->client->sess.sessionTeam;
00386         // add the sprite over the player's head
00387         attacker->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
00388         attacker->client->ps.eFlags |= EF_AWARD_DEFEND;
00389         attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00390 
00391         return;
00392     }
00393 
00394     // flag and flag carrier area defense bonuses
00395 
00396     // we have to find the flag and carrier entities
00397 
00398 #ifdef MISSIONPACK  
00399     if( g_gametype.integer == GT_OBELISK ) {
00400         // find the team obelisk
00401         switch (attacker->client->sess.sessionTeam) {
00402         case TEAM_RED:
00403             c = "team_redobelisk";
00404             break;
00405         case TEAM_BLUE:
00406             c = "team_blueobelisk";
00407             break;      
00408         default:
00409             return;
00410         }
00411         
00412     } else if (g_gametype.integer == GT_HARVESTER ) {
00413         // find the center obelisk
00414         c = "team_neutralobelisk";
00415     } else {
00416 #endif
00417     // find the flag
00418     switch (attacker->client->sess.sessionTeam) {
00419     case TEAM_RED:
00420         c = "team_CTF_redflag";
00421         break;
00422     case TEAM_BLUE:
00423         c = "team_CTF_blueflag";
00424         break;      
00425     default:
00426         return;
00427     }
00428     // find attacker's team's flag carrier
00429     for (i = 0; i < g_maxclients.integer; i++) {
00430         carrier = g_entities + i;
00431         if (carrier->inuse && carrier->client->ps.powerups[flag_pw])
00432             break;
00433         carrier = NULL;
00434     }
00435 #ifdef MISSIONPACK
00436     }
00437 #endif
00438     flag = NULL;
00439     while ((flag = G_Find (flag, FOFS(classname), c)) != NULL) {
00440         if (!(flag->flags & FL_DROPPED_ITEM))
00441             break;
00442     }
00443 
00444     if (!flag)
00445         return; // can't find attacker's flag
00446 
00447     // ok we have the attackers flag and a pointer to the carrier
00448 
00449     // check to see if we are defending the base's flag
00450     VectorSubtract(targ->r.currentOrigin, flag->r.currentOrigin, v1);
00451     VectorSubtract(attacker->r.currentOrigin, flag->r.currentOrigin, v2);
00452 
00453     if ( ( ( VectorLength(v1) < CTF_TARGET_PROTECT_RADIUS &&
00454         trap_InPVS(flag->r.currentOrigin, targ->r.currentOrigin ) ) ||
00455         ( VectorLength(v2) < CTF_TARGET_PROTECT_RADIUS &&
00456         trap_InPVS(flag->r.currentOrigin, attacker->r.currentOrigin ) ) ) &&
00457         attacker->client->sess.sessionTeam != targ->client->sess.sessionTeam) {
00458 
00459         // we defended the base flag
00460         AddScore(attacker, targ->r.currentOrigin, CTF_FLAG_DEFENSE_BONUS);
00461         attacker->client->pers.teamState.basedefense++;
00462 
00463         attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00464         // add the sprite over the player's head
00465         attacker->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
00466         attacker->client->ps.eFlags |= EF_AWARD_DEFEND;
00467         attacker->client->rewardTime = level.time + REWARD_SPRITE_TIME;
00468 
00469         return;
00470     }
00471 
00472     if (carrier && carrier != attacker) {
00473         VectorSubtract(targ->r.currentOrigin, carrier->r.currentOrigin, v1);
00474         VectorSubtract(attacker->r.currentOrigin, carrier->r.currentOrigin, v1);
00475 
00476         if ( ( ( VectorLength(v1) < CTF_ATTACKER_PROTECT_RADIUS &&
00477             trap_InPVS(carrier->r.currentOrigin, targ->r.currentOrigin ) ) ||
00478             ( VectorLength(v2) < CTF_ATTACKER_PROTECT_RADIUS &&
00479                 trap_InPVS(carrier->r.currentOrigin, attacker->r.currentOrigin ) ) ) &&
00480             attacker->client->sess.sessionTeam != targ->client->sess.sessionTeam) {
00481             AddScore(attacker, targ->r.currentOrigin, CTF_CARRIER_PROTECT_BONUS);
00482             attacker->client->pers.teamState.carrierdefense++;
00483 
00484             attacker->client->ps.persistant[PERS_DEFEND_COUNT]++;
00485             // add the sprite over the player's head
00486             attacker->client->