codemp/game/g_saga.c

Go to the documentation of this file.
00001 // Copyright (C) 2000-2002 Raven Software, Inc.
00002 //
00003 /*****************************************************************************
00004  * name:                g_saga.c
00005  *
00006  * desc:                Game-side module for Siege gametype.
00007  *
00008  * $Author: Rich Whitehouse $ 
00009  * $Revision: 1.6 $
00010  *
00011  *****************************************************************************/
00012 #include "g_local.h"
00013 #include "bg_saga.h"
00014 
00015 #define SIEGEITEM_STARTOFFRADAR 8
00016 
00017 static char             team1[512];
00018 static char             team2[512];
00019 
00020 siegePers_t     g_siegePersistant = {qfalse, 0, 0};
00021 
00022 int                     imperial_goals_required = 0;
00023 int                     imperial_goals_completed = 0;
00024 int                     rebel_goals_required = 0;
00025 int                     rebel_goals_completed = 0;
00026 
00027 int                     imperial_time_limit = 0;
00028 int                     rebel_time_limit = 0;
00029 
00030 int                     gImperialCountdown = 0;
00031 int                     gRebelCountdown = 0;
00032 
00033 int                     rebel_attackers = 0;
00034 int                     imperial_attackers = 0;
00035 
00036 qboolean        gSiegeRoundBegun = qfalse;
00037 qboolean        gSiegeRoundEnded = qfalse;
00038 qboolean        gSiegeRoundWinningTeam = 0;
00039 int                     gSiegeBeginTime = Q3_INFINITE;
00040 
00041 int                     g_preroundState = 0; //default to starting as spec (1 is starting ingame)
00042 
00043 void LogExit( const char *string );
00044 void SetTeamQuick(gentity_t *ent, int team, qboolean doBegin);
00045 
00046 static char gParseObjectives[MAX_SIEGE_INFO_SIZE];
00047 static char gObjectiveCfgStr[1024];
00048 
00049 //go through all classes on a team and register their
00050 //weapons and items for precaching.
00051 void G_SiegeRegisterWeaponsAndHoldables(int team)
00052 {
00053         siegeTeam_t *stm = BG_SiegeFindThemeForTeam(team);
00054 
00055         if (stm)
00056         {
00057                 int i = 0;
00058                 siegeClass_t *scl;
00059                 while (i < stm->numClasses)
00060                 {
00061                         scl = stm->classes[i];
00062 
00063                         if (scl)
00064                         {
00065                                 int j = 0;
00066                                 while (j < WP_NUM_WEAPONS)
00067                                 {
00068                                         if (scl->weapons & (1 << j))
00069                                         { //we use this weapon so register it.
00070                                                 RegisterItem(BG_FindItemForWeapon(j));
00071                                         }
00072                                         j++;
00073                                 }
00074                                 j = 0;
00075                                 while (j < HI_NUM_HOLDABLE)
00076                                 {
00077                                         if (scl->invenItems & (1 << j))
00078                                         { //we use this item so register it.
00079                                                 RegisterItem(BG_FindItemForHoldable(j));
00080                                         }
00081                                         j++;
00082                                 }
00083                         }
00084                         i++;
00085                 }
00086         }
00087 }
00088 
00089 //tell clients that this team won and print it on their scoreboard for intermission
00090 //or whatever.
00091 void SiegeSetCompleteData(int team)
00092 {
00093         trap_SetConfigstring(CS_SIEGE_WINTEAM, va("%i", team));
00094 }
00095 
00096 void InitSiegeMode(void)
00097 {
00098         vmCvar_t                mapname;
00099         char                    levelname[512];
00100         char                    teamIcon[128];
00101         char                    goalreq[64];
00102         char                    teams[2048];
00103         char                    objective[MAX_SIEGE_INFO_SIZE];
00104         char                    objecStr[8192];
00105         int                             len = 0;
00106         int                             i = 0;
00107 //      int                             j = 0;
00108         int                             objectiveNumTeam1 = 0;
00109         int                             objectiveNumTeam2 = 0;
00110         fileHandle_t    f;
00111 
00112         if (g_gametype.integer != GT_SIEGE)
00113         {
00114                 goto failure;
00115         }
00116 
00117         //reset
00118         SiegeSetCompleteData(0);
00119 
00120         //get pers data in case it existed from last level
00121         if (g_siegeTeamSwitch.integer)
00122         {
00123                 trap_SiegePersGet(&g_siegePersistant);
00124                 if (g_siegePersistant.beatingTime)
00125                 {
00126                         trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, va("%i", g_siegePersistant.lastTime));
00127                 }
00128                 else
00129                 {
00130                         trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0");
00131                 }
00132         }
00133         else
00134         { //hmm, ok, nothing.
00135                 trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0");
00136         }
00137 
00138         imperial_goals_completed = 0;
00139         rebel_goals_completed = 0;
00140 
00141         trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM );
00142 
00143         Com_sprintf(levelname, sizeof(levelname), "maps/%s.siege\0", mapname.string);
00144 
00145         if (!levelname || !levelname[0])
00146         {
00147                 goto failure;
00148         }
00149 
00150         len = trap_FS_FOpenFile(levelname, &f, FS_READ);
00151 
00152         if (!f || len >= MAX_SIEGE_INFO_SIZE)
00153         {
00154                 goto failure;
00155         }
00156 
00157         trap_FS_Read(siege_info, len, f);
00158 
00159         trap_FS_FCloseFile(f);
00160 
00161         siege_valid = 1;
00162 
00163         //See if players should be specs or ingame preround
00164         if (BG_SiegeGetPairedValue(siege_info, "preround_state", teams))
00165         {
00166                 if (teams[0])
00167                 {
00168                         g_preroundState = atoi(teams);
00169                 }
00170         }
00171 
00172         if (BG_SiegeGetValueGroup(siege_info, "Teams", teams))
00173         {
00174                 if (g_siegeTeam1.string[0] && Q_stricmp(g_siegeTeam1.string, "none"))
00175                 { //check for override
00176                         strcpy(team1, g_siegeTeam1.string);
00177                 }
00178                 else
00179                 { //otherwise use level default
00180                         BG_SiegeGetPairedValue(teams, "team1", team1);
00181                 }
00182 
00183                 if (g_siegeTeam2.string[0] && Q_stricmp(g_siegeTeam2.string, "none"))
00184                 { //check for override
00185                         strcpy(team2, g_siegeTeam2.string);
00186                 }
00187                 else
00188                 { //otherwise use level default
00189                         BG_SiegeGetPairedValue(teams, "team2", team2);
00190                 }
00191         }
00192         else
00193         {
00194                 G_Error("Siege teams not defined");
00195         }
00196 
00197         if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives))
00198         {
00199                 if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon))
00200                 {
00201                         trap_Cvar_Set( "team2_icon", teamIcon);
00202                 }
00203 
00204                 if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq))
00205                 {
00206                         rebel_goals_required = atoi(goalreq);
00207                 }
00208                 if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq))
00209                 {
00210                         rebel_time_limit = atoi(goalreq)*1000;
00211                         if (g_siegeTeamSwitch.integer &&
00212                                 g_siegePersistant.beatingTime)
00213                         {
00214                                 gRebelCountdown = level.time + g_siegePersistant.lastTime;
00215                         }
00216                         else
00217                         {
00218                                 gRebelCountdown = level.time + rebel_time_limit;
00219                         }
00220                 }
00221                 if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq))
00222                 {
00223                         rebel_attackers = atoi(goalreq);
00224                 }
00225         }
00226 
00227         if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives))
00228         {
00229 
00230                 if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon))
00231                 {
00232                         trap_Cvar_Set( "team1_icon", teamIcon);
00233                 }
00234 
00235                 if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq))
00236                 {
00237                         imperial_goals_required = atoi(goalreq);
00238                 }
00239                 if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq))
00240                 {
00241                         if (rebel_time_limit)
00242                         {
00243                                 Com_Printf("Tried to set imperial time limit, but there's already a rebel time limit!\nOnly one team can have a time limit.\n");
00244                         }
00245                         else
00246                         {
00247                                 imperial_time_limit = atoi(goalreq)*1000;
00248                                 if (g_siegeTeamSwitch.integer &&
00249                                         g_siegePersistant.beatingTime)
00250                                 {
00251                                         gImperialCountdown = level.time + g_siegePersistant.lastTime;
00252                                 }
00253                                 else
00254                                 {
00255                                         gImperialCountdown = level.time + imperial_time_limit;
00256                                 }
00257                         }
00258                 }
00259                 if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq))
00260                 {
00261                         imperial_attackers = atoi(goalreq);
00262                 }
00263         }
00264 
00265         //Load the player class types
00266         BG_SiegeLoadClasses(NULL);
00267 
00268         if (!bgNumSiegeClasses)
00269         { //We didn't find any?!
00270                 G_Error("Couldn't find any player classes for Siege");
00271         }
00272 
00273         /*
00274         //We could probably just see what teams are used on this level,
00275         //then see what classes are used by those teams, and then precache
00276         //all weapons for said classes. However, I'm just going to do them
00277         //all for now.
00278         while (i < bgNumSiegeClasses)
00279         {
00280                 cl = &bgSiegeClasses[i];
00281                 j = 0;
00282 
00283                 while (j < WP_NUM_WEAPONS)
00284                 {
00285                         if (cl->weapons & (1 << j))
00286                         { //we use this weapon so register it.
00287                                 RegisterItem(BG_FindItemForWeapon(j));
00288                         }
00289 
00290                         j++;
00291                 }
00292 
00293                 i++;
00294         }
00295         */
00296         //Ok, I'm adding inventory item precaching now, so I'm finally going to optimize this
00297         //to only do weapons/items for the current teams used on the level.
00298 
00299         //Now load the teams since we have class data.
00300         BG_SiegeLoadTeams();
00301 
00302         if (!bgNumSiegeTeams)
00303         { //React same as with classes.
00304                 G_Error("Couldn't find any player teams for Siege");
00305         }
00306 
00307         //Get and set the team themes for each team. This will control which classes can be
00308         //used on each team.
00309         if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives))
00310         {
00311                 if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq))
00312                 {
00313                         BG_SiegeSetTeamTheme(SIEGETEAM_TEAM1, goalreq);
00314                 }
00315 
00316                 //Now count up the objectives for this team.
00317                 i = 1;
00318                 strcpy(objecStr, va("Objective%i", i));
00319                 while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective))
00320                 {
00321                         objectiveNumTeam1++;
00322                         i++;
00323                         strcpy(objecStr, va("Objective%i", i));
00324                 }
00325         }
00326         if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives))
00327         {
00328                 if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq))
00329                 {
00330                         BG_SiegeSetTeamTheme(SIEGETEAM_TEAM2, goalreq);
00331                 }
00332 
00333                 //Now count up the objectives for this team.
00334                 i = 1;
00335                 strcpy(objecStr, va("Objective%i", i));
00336                 while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective))
00337                 {
00338                         objectiveNumTeam2++;
00339                         i++;
00340                         strcpy(objecStr, va("Objective%i", i));
00341                 }
00342         }
00343 
00344         //Set the configstring to show status of all current objectives
00345         strcpy(gObjectiveCfgStr, "t1");
00346         while (objectiveNumTeam1 > 0)
00347         { //mark them all as not completed since we just initialized
00348                 Q_strcat(gObjectiveCfgStr, 1024, "-0");
00349                 objectiveNumTeam1--;
00350         }
00351         //Finished doing team 1's objectives, now do team 2's
00352         Q_strcat(gObjectiveCfgStr, 1024, "|t2");
00353         while (objectiveNumTeam2 > 0)
00354         {
00355                 Q_strcat(gObjectiveCfgStr, 1024, "-0");
00356                 objectiveNumTeam2--;
00357         }
00358 
00359         //And finally set the actual config string
00360         trap_SetConfigstring(CS_SIEGE_OBJECTIVES, gObjectiveCfgStr);
00361 
00362         //precache saber data for classes that use sabers on both teams
00363         BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM1);
00364         BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM2);
00365 
00366         G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM1);
00367         G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM2);
00368 
00369         return;
00370 
00371 failure:
00372         siege_valid = 0;
00373 }
00374 
00375 void G_SiegeSetObjectiveComplete(int team, int objective, qboolean failIt)
00376 {
00377         char *p = NULL;
00378         int onObjective = 0;
00379 
00380         if (team == SIEGETEAM_TEAM1)
00381         {
00382                 p = strstr(gObjectiveCfgStr, "t1");
00383         }
00384         else if (team == SIEGETEAM_TEAM2)
00385         {
00386                 p = strstr(gObjectiveCfgStr, "t2");
00387         }
00388 
00389         if (!p)
00390         {
00391                 assert(0);
00392                 return;
00393         }
00394 
00395         //Parse from the beginning of this team's objectives until we get to the desired objective
00396         //number.
00397         while (p && *p && *p != '|')
00398         {
00399                 if (*p == '-')
00400                 {
00401                         onObjective++;
00402                 }
00403 
00404                 if (onObjective == objective)
00405                 { //this is the one we want
00406                         //Move to the next char, the status of this objective
00407                         p++;
00408 
00409                         //Now change it from '0' to '1' if we are completeing the objective
00410                         //or vice versa if the objective has been taken away
00411                         if (failIt)
00412                         {
00413                                 *p = '0';
00414                         }
00415                         else
00416                         {
00417                                 *p = '1';
00418                         }
00419                         break;
00420                 }
00421 
00422                 p++;
00423         }
00424 
00425         //Now re-update the configstring.
00426         trap_SetConfigstring(CS_SIEGE_OBJECTIVES, gObjectiveCfgStr);
00427 }
00428 
00429 //Returns qtrue if objective complete currently, otherwise qfalse
00430 qboolean G_SiegeGetCompletionStatus(int team, int objective)
00431 {
00432         char *p = NULL;
00433         int onObjective = 0;
00434 
00435         if (team == SIEGETEAM_TEAM1)
00436         {
00437                 p = strstr(gObjectiveCfgStr, "t1");
00438         }
00439         else if (team == SIEGETEAM_TEAM2)
00440         {
00441                 p = strstr(gObjectiveCfgStr, "t2");
00442         }
00443 
00444         if (!p)
00445         {
00446                 assert(0);
00447                 return qfalse;
00448         }
00449 
00450         //Parse from the beginning of this team's objectives until we get to the desired objective
00451         //number.
00452         while (p && *p && *p != '|')
00453         {
00454                 if (*p == '-')
00455                 {
00456                         onObjective++;
00457                 }
00458 
00459                 if (onObjective == objective)
00460                 { //this is the one we want
00461                         //Move to the next char, the status of this objective
00462                         p++;
00463 
00464                         //return qtrue if it's '1', qfalse if it's anything else
00465                         if (*p == '1')
00466                         {
00467                                 return qtrue;
00468                         }
00469                         else
00470                         {
00471                                 return qfalse;
00472                         }
00473                         break;
00474                 }
00475 
00476                 p++;
00477         }
00478 
00479         return qfalse;
00480 }
00481 
00482 void UseSiegeTarget(gentity_t *other, gentity_t *en, char *target)
00483 { //actually use the player which triggered the object which triggered the siege objective to trigger the target
00484         gentity_t               *t;
00485         gentity_t               *ent;
00486 
00487         if ( !en || !en->client )
00488         { //looks like we don't have access to a player, so just use the activating entity
00489                 ent = other;
00490         }
00491         else
00492         {
00493                 ent = en;
00494         }
00495 
00496         if (!en)
00497         {
00498                 return;
00499         }
00500 
00501         if ( !target )
00502         {
00503                 return;
00504         }
00505 
00506         t = NULL;
00507         while ( (t = G_Find (t, FOFS(targetname), target)) != NULL )
00508         {
00509                 if ( t == ent )
00510                 {
00511                         G_Printf ("WARNING: Entity used itself.\n");
00512                 }
00513                 else
00514                 {
00515                         if ( t->use )
00516                         {
00517                                 GlobalUse(t, ent, ent);
00518                         }
00519                 }
00520                 if ( !ent->inuse )
00521                 {
00522                         G_Printf("entity was removed while using targets\n");
00523                         return;
00524                 }
00525         }
00526 }
00527 
00528 void SiegeBroadcast_OBJECTIVECOMPLETE(int team, int client, int objective)
00529 {
00530         gentity_t *te;
00531         vec3_t nomatter;
00532 
00533         VectorClear(nomatter);
00534 
00535         te = G_TempEntity( nomatter, EV_SIEGE_OBJECTIVECOMPLETE );
00536         te->r.svFlags |= SVF_BROADCAST;
00537         te->s.eventParm = team;
00538         te->s.weapon = client;
00539         te->s.trickedentindex = objective;
00540 }
00541 
00542 void SiegeBroadcast_ROUNDOVER(int winningteam, int winningclient)
00543 {
00544         gentity_t *te;
00545         vec3_t nomatter;
00546 
00547         VectorClear(nomatter);
00548 
00549         te = G_TempEntity( nomatter, EV_SIEGE_ROUNDOVER );
00550         te->r.svFlags |= SVF_BROADCAST;
00551         te->s.eventParm = winningteam;
00552         te->s.weapon = winningclient;
00553 }
00554 
00555 void BroadcastObjectiveCompletion(int team, int objective, int final, int client)
00556 {
00557         if (client != ENTITYNUM_NONE && g_entities[client].client && g_entities[client].client->sess.sessionTeam == team)
00558         { //guy who completed this objective gets points, providing he's on the opposing team
00559                 AddScore(&g_entities[client], g_entities[client].client->ps.origin, SIEGE_POINTS_OBJECTIVECOMPLETED);
00560         }
00561 
00562         SiegeBroadcast_OBJECTIVECOMPLETE(team, client, objective);
00563         //G_Printf("Broadcast goal completion team %i objective %i final %i\n", team, objective, final);
00564 }
00565 
00566 void AddSiegeWinningTeamPoints(int team, int winner)
00567 {
00568         int i = 0;
00569         gentity_t *ent;
00570 
00571         while (i < MAX_CLIENTS)
00572         {
00573                 ent = &g_entities[i];
00574 
00575                 if (ent && ent->client && ent->client->sess.sessionTeam == team)
00576                 {
00577                         if (i == winner)
00578                         {
00579                                 AddScore(ent, ent->client->ps.origin, SIEGE_POINTS_TEAMWONROUND+SIEGE_POINTS_FINALOBJECTIVECOMPLETED);
00580                         }
00581                         else
00582                         {
00583                                 AddScore(ent, ent->client->ps.origin, SIEGE_POINTS_TEAMWONROUND);
00584                         }
00585                 }
00586 
00587                 i++;
00588         }
00589 }
00590 
00591 void SiegeClearSwitchData(void)
00592 {
00593         memset(&g_siegePersistant, 0, sizeof(g_siegePersistant));
00594         trap_SiegePersSet(&g_siegePersistant);
00595 }
00596 
00597 void SiegeDoTeamAssign(void)
00598 {
00599         int i = 0;
00600         gentity_t *ent;
00601 
00602         //yeah, this is great...
00603         while (i < MAX_CLIENTS)
00604         {
00605                 ent = &g_entities[i];
00606 
00607                 if (ent->inuse && ent->client &&
00608                         ent->client->pers.connected == CON_CONNECTED)
00609                 { //a connected client, switch his frickin teams around
00610                         if (ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM1)
00611                         {
00612                                 ent->client->sess.siegeDesiredTeam = SIEGETEAM_TEAM2;
00613                         }
00614                         else if (ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM2)
00615                         {
00616                                 ent->client->sess.siegeDesiredTeam = SIEGETEAM_TEAM1;
00617                         }
00618 
00619                         if (ent->client->sess.sessionTeam == SIEGETEAM_TEAM1)
00620                         {
00621                                 SetTeamQuick(ent, SIEGETEAM_TEAM2, qfalse);
00622                         }
00623                         else if (ent->client->sess.sessionTeam == SIEGETEAM_TEAM2)
00624                         {
00625                                 SetTeamQuick(ent, SIEGETEAM_TEAM1, qfalse);
00626                         }
00627                 }
00628                 i++;
00629         }
00630 }
00631 
00632 void SiegeTeamSwitch(int winTeam, int winTime)
00633 {
00634         trap_SiegePersGet(&g_siegePersistant);
00635         if (g_siegePersistant.beatingTime)
00636         { //was already in "switched" mode, change back
00637                 //announce the winning team.
00638                 //either the first team won again, or the second
00639                 //team beat the time set by the initial team. In any
00640                 //case the winTeam here is the overall winning team.
00641                 SiegeSetCompleteData(winTeam);
00642                 SiegeClearSwitchData();
00643         }
00644         else
00645         { //go into "beat their time" mode
00646                 g_siegePersistant.beatingTime = qtrue;
00647         g_siegePersistant.lastTeam = winTeam;
00648                 g_siegePersistant.lastTime = winTime;
00649 
00650                 trap_SiegePersSet(&g_siegePersistant);
00651         }
00652 }
00653 
00654 void SiegeRoundComplete(int winningteam, int winningclient)
00655 {
00656         vec3_t nomatter;
00657         char teamstr[1024];
00658         int originalWinningClient = winningclient;
00659 
00660         //G_Printf("Team %i won\n", winningteam);
00661 
00662         if (winningclient != ENTITYNUM_NONE && g_entities[winningclient].client &&
00663                 g_entities[winningclient].client->sess.sessionTeam != winningteam)
00664         { //this person just won the round for the other team..
00665                 winningclient = ENTITYNUM_NONE;
00666         }
00667 
00668         VectorClear(nomatter);
00669 
00670         SiegeBroadcast_ROUNDOVER(winningteam, winningclient);
00671 
00672         AddSiegeWinningTeamPoints(winningteam, winningclient);
00673 
00674         //Instead of exiting like this, fire off a target, and let it handle things.
00675         //Can be a script or whatever the designer wants.
00676         if (winningteam == SIEGETEAM_TEAM1)
00677         {
00678                 Com_sprintf(teamstr, sizeof(teamstr), team1);
00679         }
00680         else
00681         {
00682                 Com_sprintf(teamstr, sizeof(teamstr), team2);
00683         }
00684 
00685         trap_SetConfigstring(CS_SIEGE_STATE, va("3|%i", level.time)); //ended
00686         gSiegeRoundBegun = qfalse;
00687         gSiegeRoundEnded = qtrue;
00688         gSiegeRoundWinningTeam = winningteam;
00689 
00690         if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
00691         {
00692                 if (!BG_SiegeGetPairedValue(gParseObjectives, "roundover_target", teamstr))
00693                 { //didn't find the name of the thing to target upon win, just logexit now then.
00694                         LogExit( "Objectives completed" );
00695                         return;
00696                 }
00697                 
00698                 if (originalWinningClient == ENTITYNUM_NONE)
00699                 { //oh well, just find something active and use it then.
00700             int i = 0;
00701                         gentity_t *ent;
00702 
00703                         while (i < MAX_CLIENTS)
00704                         {
00705                                 ent = &g_entities[i];
00706 
00707                                 if (ent->inuse)
00708                                 { //sure, you'll do.
00709                     originalWinningClient = ent->s.number;
00710                                         break;
00711                                 }
00712 
00713                                 i++;
00714                         }
00715                 }
00716                 G_UseTargets2(&g_entities[originalWinningClient], &g_entities[originalWinningClient], teamstr);
00717         }
00718 
00719         if (g_siegeTeamSwitch.integer &&
00720                 (imperial_time_limit || rebel_time_limit))
00721         { //handle stupid team switching crap
00722                 int time = 0;
00723                 if (imperial_time_limit)
00724                 {
00725                         time = imperial_time_limit-(gImperialCountdown-level.time);
00726                 }
00727                 else if (rebel_time_limit)
00728                 {
00729                         time = rebel_time_limit-(gRebelCountdown-level.time);
00730                 }
00731 
00732                 if (time < 1)
00733                 {
00734                         time = 1;
00735                 }
00736                 SiegeTeamSwitch(winningteam, time);
00737         }
00738         else
00739         { //assure it's clear for next round
00740                 SiegeClearSwitchData();
00741         }
00742 }
00743 
00744 void G_ValidateSiegeClassForTeam(gentity_t *ent, int team)
00745 {
00746         siegeClass_t *scl;
00747         siegeTeam_t *stm;
00748         int newClassIndex = -1;
00749         if (ent->client->siegeClass == -1)
00750         { //uh.. sure.
00751                 return;
00752         }
00753 
00754         scl = &bgSiegeClasses[ent->client->siegeClass];
00755 
00756         stm = BG_SiegeFindThemeForTeam(team);
00757         if (stm)
00758         {
00759                 int i = 0;
00760 
00761                 while (i < stm->numClasses)
00762                 { //go through the team and see its valid classes, can we find one that matches our current player class?
00763                         if (stm->classes[i])
00764                         {
00765                                 if (!Q_stricmp(scl->name, stm->classes[i]->name))
00766                                 { //the class we're using is already ok for this team.
00767                                         return;
00768                                 }
00769                                 if (stm->classes[i]->playerClass == scl->playerClass ||
00770                                         newClassIndex == -1)
00771                                 {
00772                                         newClassIndex = i;
00773                                 }
00774                         }
00775                         i++;
00776                 }
00777 
00778                 if (newClassIndex != -1)
00779                 { //ok, let's find it in the global class array
00780                         ent->client->siegeClass = BG_SiegeFindClassIndexByName(stm->classes[newClassIndex]->name);
00781                         strcpy(ent->client->sess.siegeClass, stm->classes[newClassIndex]->name);
00782                 }
00783         }
00784 }
00785 
00786 //bypass most of the normal checks in SetTeam
00787 void SetTeamQuick(gentity_t *ent, int team, qboolean doBegin)
00788 {
00789         char userinfo[MAX_INFO_STRING];
00790 
00791         trap_GetUserinfo( ent->s.number, userinfo, sizeof( userinfo ) );
00792 
00793         if (g_gametype.integer == GT_SIEGE)
00794         {
00795                 G_ValidateSiegeClassForTeam(ent, team);
00796         }
00797 
00798         ent->client->sess.sessionTeam = team;
00799 
00800         if (team == TEAM_SPECTATOR)
00801         {
00802                 ent->client->sess.spectatorState = SPECTATOR_FREE;
00803                 Info_SetValueForKey(userinfo, "team", "s");
00804         }
00805         else
00806         {
00807                 ent->client->sess.spectatorState = SPECTATOR_NOT;
00808                 if (team == TEAM_RED)
00809                 {
00810                         Info_SetValueForKey(userinfo, "team", "r");
00811                 }
00812                 else if (team == TEAM_BLUE)
00813                 {
00814                         Info_SetValueForKey(userinfo, "team", "b");
00815                 }
00816                 else
00817                 {
00818                         Info_SetValueForKey(userinfo, "team", "?");
00819                 }
00820         }
00821 
00822         trap_SetUserinfo( ent->s.number, userinfo );
00823 
00824         ent->client->sess.spectatorClient = 0;
00825 
00826         ent->client->pers.teamState.state = TEAM_BEGIN;
00827 
00828         ClientUserinfoChanged( ent->s.number );
00829 
00830         if (doBegin)
00831         {
00832                 ClientBegin( ent->s.number, qfalse );
00833         }
00834 }
00835 
00836 void SiegeRespawn(gentity_t *ent)
00837 {
00838         gentity_t *tent;
00839 
00840         if (ent->client->sess.sessionTeam != ent->client->sess.siegeDesiredTeam)
00841         {
00842                 SetTeamQuick(ent, ent->client->sess.siegeDesiredTeam, qtrue);
00843         }
00844         else
00845         {
00846                 ClientSpawn(ent);
00847                 // add a teleportation effect
00848                 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
00849                 tent->s.clientNum = ent->s.clientNum;
00850         }
00851 }
00852 
00853 void SiegeBeginRound(int entNum)
00854 { //entNum is just used as something to fire targets from.
00855         char targname[1024];
00856 
00857         if (!g_preroundState)
00858         { //if players are not ingame on round start then respawn them now
00859                 int i = 0;
00860                 gentity_t *ent;
00861                 qboolean spawnEnt = qfalse;
00862 
00863                 //respawn everyone now
00864                 while (i < MAX_CLIENTS)
00865                 {
00866                         ent = &g_entities[i];
00867 
00868                         if (ent->inuse && ent->client)
00869                         {
00870                                 if (ent->client->sess.sessionTeam != TEAM_SPECTATOR &&
00871                                         !(ent->client->ps.pm_flags & PMF_FOLLOW))
00872                                 { //not a spec, just respawn them
00873                                         spawnEnt = qtrue;
00874                                 }
00875                                 else if (ent->client->sess.sessionTeam == TEAM_SPECTATOR &&
00876                                         (ent->client->sess.siegeDesiredTeam == TEAM_RED ||
00877                                          ent->client->sess.siegeDesiredTeam == TEAM_BLUE))
00878                                 { //spectator but has a desired team
00879                                         spawnEnt = qtrue;
00880                                 }
00881                         }
00882 
00883                         if (spawnEnt)
00884                         {
00885                                 SiegeRespawn(ent);
00886 
00887                                 spawnEnt = qfalse;
00888                         }
00889                         i++;
00890                 }
00891         }
00892 
00893         //Now check if there's something to fire off at the round start, if so do it.
00894         if (BG_SiegeGetPairedValue(siege_info, "roundbegin_target", targname))
00895         {
00896                 if (targname[0])
00897                 {
00898                         G_UseTargets2(&g_entities[entNum], &g_entities[entNum], targname);
00899                 }
00900         }
00901 
00902         trap_SetConfigstring(CS_SIEGE_STATE, va("0|%i", level.time)); //we're ready to g0g0g0
00903 }
00904 
00905 void SiegeCheckTimers(void)
00906 {
00907         int i=0;
00908         gentity_t *ent;
00909         int numTeam1 = 0;
00910         int numTeam2 = 0;
00911 
00912         if (g_gametype.integer != GT_SIEGE)
00913         {
00914                 return;
00915         }
00916 
00917         if (level.intermissiontime)
00918         {
00919                 return;
00920         }
00921 
00922         if (gSiegeRoundEnded)
00923         {
00924                 return;
00925         }
00926 
00927         if (!gSiegeRoundBegun)
00928         { //check if anyone is active on this team - if not, keep the timer set up.
00929                 i = 0;
00930 
00931                 while (i < MAX_CLIENTS)
00932                 {
00933                         ent = &g_entities[i];
00934 
00935                         if (ent && ent->inuse && ent->client &&
00936                                 ent->client->pers.connected == CON_CONNECTED &&
00937                                 ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM1)
00938                         {
00939                                 numTeam1++;
00940                         }
00941                         i++;
00942                 }
00943 
00944                 i = 0;
00945 
00946                 while (i < MAX_CLIENTS)
00947                 {
00948                         ent = &g_entities[i];
00949 
00950                         if (ent && ent->inuse && ent->client &&
00951                                 ent->client->pers.connected == CON_CONNECTED &&
00952                                 ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM2)
00953                         {
00954                                 numTeam2++;
00955                         }
00956                         i++;
00957                 }
00958 
00959                 if (g_siegeTeamSwitch.integer &&
00960                         g_siegePersistant.beatingTime)
00961                 {
00962                         gImperialCountdown = level.time + g_siegePersistant.lastTime;
00963                         gRebelCountdown = level.time + g_siegePersistant.lastTime;
00964                 }
00965                 else
00966                 {
00967                         gImperialCountdown = level.time + imperial_time_limit;
00968                         gRebelCountdown = level.time + rebel_time_limit;
00969                 }
00970         }
00971 
00972         if (imperial_time_limit)
00973         { //team1
00974                 if (gImperialCountdown < level.time)
00975                 {
00976                         SiegeRoundComplete(SIEGETEAM_TEAM2, ENTITYNUM_NONE);
00977                         imperial_time_limit = 0;
00978                         return;
00979                 }
00980         }
00981 
00982         if (rebel_time_limit)
00983         { //team2
00984                 if (gRebelCountdown < level.time)
00985                 {
00986                         SiegeRoundComplete(SIEGETEAM_TEAM1, ENTITYNUM_NONE);
00987                         rebel_time_limit = 0;
00988                         return;
00989                 }
00990         }
00991 
00992         if (!gSiegeRoundBegun)
00993         {
00994                 if (!numTeam1 || !numTeam2)
00995                 { //don't have people on both teams yet.
00996                         gSiegeBeginTime = level.time + SIEGE_ROUND_BEGIN_TIME;
00997                         trap_SetConfigstring(CS_SIEGE_STATE, "1"); //"waiting for players on both teams"
00998                 }
00999                 else if (gSiegeBeginTime < level.time)
01000                 { //mark the round as having begun
01001                         gSiegeRoundBegun = qtrue;
01002                         SiegeBeginRound(i); //perform any round start tasks
01003                 }
01004                 else if (gSiegeBeginTime > (level.time + SIEGE_ROUND_BEGIN_TIME))
01005                 {
01006                         gSiegeBeginTime = level.time + SIEGE_ROUND_BEGIN_TIME;
01007                 }
01008                 else
01009                 {
01010                         trap_SetConfigstring(CS_SIEGE_STATE, va("2|%i", gSiegeBeginTime - SIEGE_ROUND_BEGIN_TIME)); //getting ready to begin
01011                 }
01012         }
01013 }
01014 
01015 void SiegeObjectiveCompleted(int team, int objective, int final, int client)
01016 {
01017         int goals_completed, goals_required;
01018 
01019         if (gSiegeRoundEnded)
01020         {
01021                 return;
01022         }
01023 
01024         //Update the configstring status
01025         G_SiegeSetObjectiveComplete(team, objective, qfalse);
01026 
01027         if (final != -1)
01028         {
01029                 if (team == SIEGETEAM_TEAM1)
01030                 {
01031                         imperial_goals_completed++;
01032                 }
01033                 else
01034                 {
01035                         rebel_goals_completed++;
01036                 }
01037         }
01038 
01039         if (team == SIEGETEAM_TEAM1)
01040         {
01041                 goals_completed = imperial_goals_completed;
01042                 goals_required = imperial_goals_required;
01043         }
01044         else
01045         {
01046                 goals_completed = rebel_goals_completed;
01047                 goals_required = rebel_goals_required;
01048         }
01049 
01050         if (final == 1 || goals_completed >= goals_required)
01051         {
01052                 SiegeRoundComplete(team, client);
01053         }
01054         else
01055         {
01056                 BroadcastObjectiveCompletion(team, objective, final, client);
01057         }
01058 }
01059 
01060 void siegeTriggerUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01061 {
01062         char                    teamstr[64];
01063         char                    objectivestr[64];
01064         char                    desiredobjective[MAX_SIEGE_INFO_SIZE];
01065         int                             clUser = ENTITYNUM_NONE;
01066         int                             final = 0;
01067         int                             i = 0;
01068 
01069         if (!siege_valid)
01070         {
01071                 return;
01072         }
01073 
01074         if (!(ent->s.eFlags & EF_RADAROBJECT))
01075         { //toggle radar on and exit if it is not showing up already
01076                 ent->s.eFlags |= EF_RADAROBJECT;
01077                 return;
01078         }
01079 
01080         if (activator && activator->client)
01081         { //activator will hopefully be the person who triggered this event
01082                 clUser = activator->s.number;
01083         }
01084 
01085         if (ent->side == SIEGETEAM_TEAM1)
01086         {
01087                 Com_sprintf(teamstr, sizeof(teamstr), team1);
01088         }
01089         else
01090         {
01091                 Com_sprintf(teamstr, sizeof(teamstr), team2);
01092         }
01093 
01094         if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
01095         {
01096                 Com_sprintf(objectivestr, sizeof(objectivestr), "Objective%i", ent->objective);
01097 
01098                 if (BG_SiegeGetValueGroup(gParseObjectives, objectivestr, desiredobjective))
01099                 {
01100                         if (BG_SiegeGetPairedValue(desiredobjective, "final", teamstr))
01101                         {
01102                                 final = atoi(teamstr);
01103                         }
01104 
01105                         if (BG_SiegeGetPairedValue(desiredobjective, "target", teamstr))
01106                         {
01107                                 while (teamstr[i])
01108                                 {
01109                                         if (teamstr[i] == '\r' ||
01110                                                 teamstr[i] == '\n')
01111                                         {
01112                                                 teamstr[i] = '\0';
01113                                         }
01114 
01115                                         i++;
01116                                 }
01117                                 UseSiegeTarget(other, activator, teamstr);
01118                         }
01119 
01120                         if (ent->target && ent->target[0])
01121                         { //use this too
01122                                 UseSiegeTarget(other, activator, ent->target);
01123                         }
01124 
01125                         SiegeObjectiveCompleted(ent->side, ent->objective, final, clUser);
01126                 }
01127         }
01128 }
01129 
01130 /*QUAKED info_siege_objective (1 0 1) (-16 -16 -24) (16 16 32) ? x x STARTOFFRADAR
01131 STARTOFFRADAR - start not displaying on radar, don't display until used.
01132 
01133 "objective" - specifies the objective to complete upon activation
01134 "side" - set to 1 to specify an imperial goal, 2 to specify rebels
01135 "icon" - icon that represents the objective on the radar
01136 */
01137 void SP_info_siege_objective (gentity_t *ent)
01138 {
01139         char* s;
01140 
01141         if (!siege_valid || g_gametype.integer != GT_SIEGE)
01142         {
01143                 G_FreeEntity(ent);
01144                 return;
01145         }
01146 
01147         ent->use = siegeTriggerUse;
01148         G_SpawnInt( "objective", "0", &ent->objective);
01149         G_SpawnInt( "side", "0", &ent->side);
01150 
01151         if (!ent->objective || !ent->side)
01152         { //j00 fux0red something up
01153                 G_FreeEntity(ent);
01154                 G_Printf("ERROR: info_siege_objective without an objective or side value\n");
01155                 return;
01156         }
01157 
01158         //Set it up to be drawn on radar
01159         if (!(ent->spawnflags & SIEGEITEM_STARTOFFRADAR))
01160         {
01161                 ent->s.eFlags |= EF_RADAROBJECT;
01162         }
01163 
01164         //All clients want to know where it is at all times for radar
01165         ent->r.svFlags |= SVF_BROADCAST;
01166 
01167         G_SpawnString( "icon", "", &s );
01168         
01169         if (s && s[0])
01170         { 
01171                 // We have an icon, so index it now.  We are reusing the genericenemyindex
01172                 // variable rather than adding a new one to the entity state.
01173                 ent->s.genericenemyindex = G_IconIndex(s);
01174         }
01175 
01176         ent->s.brokenLimbs = ent->side;
01177         ent->s.frame = ent->objective;
01178         trap_LinkEntity(ent);
01179 }
01180 
01181 
01182 void SiegeIconUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01183 { //toggle it on and off
01184         if (ent->s.eFlags & EF_RADAROBJECT)
01185         {
01186                 ent->s.eFlags &= ~EF_RADAROBJECT;
01187                 ent->r.svFlags &= ~SVF_BROADCAST;
01188         }
01189         else
01190         {
01191                 ent->s.eFlags |= EF_RADAROBJECT;
01192                 ent->r.svFlags |= SVF_BROADCAST;
01193         }
01194 }
01195 
01196 /*QUAKED info_siege_radaricon (1 0 1) (-16 -16 -24) (16 16 32) ? 
01197 Used to arbitrarily display radar icons at placed location. Can be used
01198 to toggle on and off.
01199 
01200 "icon" - icon that represents the objective on the radar
01201 "startoff" - if 1 start off
01202 */
01203 void SP_info_siege_radaricon (gentity_t *ent)
01204 {
01205         char* s;
01206         int i;
01207 
01208         if (!siege_valid || g_gametype.integer != GT_SIEGE)
01209         {
01210                 G_FreeEntity(ent);
01211                 return;
01212         }
01213 
01214         G_SpawnInt("startoff", "0", &i);
01215 
01216         if (!i)
01217         { //start on then
01218                 ent->s.eFlags |= EF_RADAROBJECT;
01219                 ent->r.svFlags |= SVF_BROADCAST;
01220         }
01221 
01222         G_SpawnString( "icon", "", &s );
01223         if (!s || !s[0])
01224         { //that's the whole point of the entity
01225         Com_Error(ERR_DROP, "misc_siege_radaricon without an icon");
01226                 return;
01227         }
01228 
01229         ent->use = SiegeIconUse;
01230 
01231         ent->s.genericenemyindex = G_IconIndex(s);
01232 
01233         trap_LinkEntity(ent);
01234 }
01235 
01236 void decompTriggerUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01237 {
01238         int final = 0;
01239         char teamstr[1024];
01240         char objectivestr[64];
01241         char desiredobjective[MAX_SIEGE_INFO_SIZE];
01242 
01243         if (gSiegeRoundEnded)
01244         {
01245                 return;
01246         }
01247 
01248         if (!G_SiegeGetCompletionStatus(ent->side, ent->objective))
01249         { //if it's not complete then there's nothing to do here
01250                 return;
01251         }
01252 
01253         //Update the configstring status
01254         G_SiegeSetObjectiveComplete(ent->side, ent->objective, qtrue);
01255 
01256         //Find out if this objective counts toward the final objective count
01257         if (ent->side == SIEGETEAM_TEAM1)
01258         {
01259                 Com_sprintf(teamstr, sizeof(teamstr), team1);
01260         }
01261         else
01262         {
01263                 Com_sprintf(teamstr, sizeof(teamstr), team2);
01264         }
01265 
01266         if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
01267         {
01268                 Com_sprintf(objectivestr, sizeof(objectivestr), "Objective%i", ent->objective);
01269 
01270                 if (BG_SiegeGetValueGroup(gParseObjectives, objectivestr, desiredobjective))
01271                 {
01272                         if (BG_SiegeGetPairedValue(desiredobjective, "final", teamstr))
01273                         {
01274                                 final = atoi(teamstr);
01275                         }
01276                 }
01277         }
01278 
01279         //Subtract the goal num if applicable
01280         if (final != -1)
01281         {
01282                 if (ent->side == SIEGETEAM_TEAM1)
01283                 {
01284                         imperial_goals_completed--;
01285                 }
01286                 else
01287                 {
01288                         rebel_goals_completed--;
01289                 }
01290         }
01291 }
01292 
01293 /*QUAKED info_siege_decomplete (1 0 1) (-16 -16 -24) (16 16 32)
01294 "objective" - specifies the objective to decomplete upon activation
01295 "side" - set to 1 to specify an imperial (team1) goal, 2 to specify rebels (team2)
01296 */
01297 void SP_info_siege_decomplete (gentity_t *ent)
01298 {
01299         if (!siege_valid || g_gametype.integer != GT_SIEGE)
01300         {
01301                 G_FreeEntity(ent);
01302                 return;
01303         }
01304 
01305         ent->use = decompTriggerUse;
01306         G_SpawnInt( "objective", "0", &ent->objective);
01307         G_SpawnInt( "side", "0", &ent->side);
01308 
01309         if (!ent->objective || !ent->side)
01310         { //j00 fux0red something up
01311                 G_FreeEntity(ent);
01312                 G_Printf("ERROR: info_siege_objective_decomplete without an objective or side value\n");
01313                 return;
01314         }
01315 }
01316 
01317 void siegeEndUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01318 {
01319         LogExit("Round ended");
01320 }
01321 
01322 /*QUAKED target_siege_end (1 0 1) (-16 -16 -24) (16 16 32)
01323 Do a logexit for siege when used.
01324 */
01325 void SP_target_siege_end (gentity_t *ent)
01326 {
01327         if (!siege_valid || g_gametype.integer != GT_SIEGE)
01328         {
01329                 G_FreeEntity(ent);
01330                 return;
01331         }
01332 
01333         ent->use = siegeEndUse;
01334 }
01335 
01336 #define SIEGE_ITEM_RESPAWN_TIME 20000
01337 
01338 void SiegeItemRemoveOwner(gentity_t *ent, gentity_t *carrier)
01339 {
01340         ent->genericValue2 = 0; //Remove picked-up flag
01341 
01342         ent->genericValue8 = ENTITYNUM_NONE; //Mark entity carrying us as none
01343 
01344         if (carrier)
01345         {
01346                 carrier->client->holdingObjectiveItem = 0; //The carrier is no longer carrying us
01347                 carrier->r.svFlags &= ~SVF_BROADCAST;
01348         }
01349 }
01350 
01351 static void SiegeItemRespawnEffect(gentity_t *ent, vec3_t newOrg)
01352 {
01353         vec3_t upAng;
01354 
01355         if (ent->target5 && ent->target5[0])
01356         {
01357                 G_UseTargets2(ent, ent, ent->target5);
01358         }
01359 
01360         if (!ent->genericValue10)
01361         { //no respawn effect
01362                 return;
01363         }
01364 
01365         VectorSet(upAng, 0, 0, 1);
01366 
01367         //Play it once on the current origin, and once on the origin we're respawning to.
01368         G_PlayEffectID(ent->genericValue10, ent->r.currentOrigin, upAng);
01369         G_PlayEffectID(ent->genericValue10, newOrg, upAng);
01370 }
01371 
01372 static void SiegeItemRespawnOnOriginalSpot(gentity_t *ent, gentity_t *carrier)
01373 {
01374         SiegeItemRespawnEffect(ent, ent->pos1);
01375         G_SetOrigin(ent, ent->pos1);
01376         SiegeItemRemoveOwner(ent, carrier);
01377         
01378         // Stop the item from flashing on the radar
01379         ent->s.time2 = 0;
01380 }
01381 
01382 void SiegeItemThink(gentity_t *ent)
01383 {
01384         gentity_t *carrier = NULL;
01385 
01386         if (ent->genericValue12)
01387         { //recharge health
01388                 if (ent->health > 0 && ent->health < ent->maxHealth && ent->genericValue14 < level.time)
01389                 {
01390             ent->genericValue14 = level.time + ent->genericValue13;
01391                         ent->health += ent->genericValue12;
01392                         if (ent->health > ent->maxHealth)
01393                         {
01394                                 ent->health = ent->maxHealth;
01395                         }
01396                 }
01397         }
01398 
01399         if (ent->genericValue8 != ENTITYNUM_NONE)
01400         { //Just keep sticking it on top of the owner. We need it in the same PVS as him so it will render bolted onto him properly.
01401                 carrier = &g_entities[ent->genericValue8];
01402 
01403                 if (carrier->inuse && carrier->client)
01404                 {
01405                         VectorCopy(carrier->client->ps.origin, ent->r.currentOrigin);
01406                         trap_LinkEntity(ent);
01407                 }
01408         }
01409         else if (ent->genericValue1)
01410         { //this means we want to run physics on the object
01411                 G_RunExPhys(ent, ent->radius, ent->mass, ent->random, qfalse, NULL, 0);
01412         }
01413 
01414         //Bolt us to whoever is carrying us if a client
01415         if (ent->genericValue8 < MAX_CLIENTS)
01416         {
01417                 ent->s.boltToPlayer = ent->genericValue8+1;
01418         }
01419         else
01420         {
01421                 ent->s.boltToPlayer = 0;
01422         }
01423 
01424 
01425         if (carrier)
01426         {
01427                 gentity_t *carrier = &g_entities[ent->genericValue8];
01428 
01429                 //This checking can be a bit iffy on the death stuff, but in theory we should always
01430                 //get a think in before the default minimum respawn time is exceeded.
01431                 if (!carrier->inuse || !carrier->client ||
01432                         (carrier->client->sess.sessionTeam != SIEGETEAM_TEAM1 && carrier->client->sess.sessionTeam != SIEGETEAM_TEAM2) ||
01433                         (carrier->client->ps.pm_flags & PMF_FOLLOW))
01434