codemp/game/bg_saga.c

Go to the documentation of this file.
00001 // Copyright (C) 2000-2002 Raven Software, Inc.
00002 //
00003 /*****************************************************************************
00004  * name:                bg_saga.c
00005  *
00006  * desc:                Siege module, shared for game, cgame, and ui.
00007  *
00008  * $Author: osman $ 
00009  * $Revision: 1.9 $
00010  *
00011  *****************************************************************************/
00012 #include "q_shared.h"
00013 #include "bg_saga.h"
00014 #include "bg_weapons.h"
00015 #include "bg_public.h"
00016 
00017 #define SIEGECHAR_TAB 9 //perhaps a bit hacky, but I don't think there's any define existing for "tab"
00018 
00019 //Could use strap stuff but I don't particularly care at the moment anyway.
00020 #include "../namespace_begin.h"
00021 
00022 extern int      trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
00023 extern void     trap_FS_Read( void *buffer, int len, fileHandle_t f );
00024 extern void     trap_FS_Write( const void *buffer, int len, fileHandle_t f );
00025 extern void     trap_FS_FCloseFile( fileHandle_t f );
00026 extern int      trap_FS_GetFileList(  const char *path, const char *extension, char *listbuf, int bufsize );
00027 
00028 #ifndef QAGAME //cgame, ui
00029 qhandle_t       trap_R_RegisterShaderNoMip( const char *name );
00030 #endif
00031 
00032 char            siege_info[MAX_SIEGE_INFO_SIZE];
00033 int                     siege_valid = 0;
00034 
00035 siegeTeam_t *team1Theme = NULL;
00036 siegeTeam_t *team2Theme = NULL;
00037 
00038 siegeClass_t bgSiegeClasses[MAX_SIEGE_CLASSES];
00039 int bgNumSiegeClasses = 0;
00040 
00041 siegeTeam_t bgSiegeTeams[MAX_SIEGE_TEAMS];
00042 int bgNumSiegeTeams = 0;
00043 
00044 //class flags
00045 stringID_table_t bgSiegeClassFlagNames[] =
00046 {
00047         ENUM2STRING(CFL_MORESABERDMG),
00048         ENUM2STRING(CFL_STRONGAGAINSTPHYSICAL),
00049         ENUM2STRING(CFL_FASTFORCEREGEN),
00050         ENUM2STRING(CFL_STATVIEWER),
00051         ENUM2STRING(CFL_HEAVYMELEE),
00052         ENUM2STRING(CFL_SINGLE_ROCKET),
00053         ENUM2STRING(CFL_CUSTOMSKEL),
00054         ENUM2STRING(CFL_EXTRA_AMMO),
00055         "", -1
00056 };
00057 
00058 //saber stances
00059 stringID_table_t StanceTable[] =
00060 {
00061         ENUM2STRING(SS_NONE),
00062         ENUM2STRING(SS_FAST),
00063         ENUM2STRING(SS_MEDIUM),
00064         ENUM2STRING(SS_STRONG),
00065         ENUM2STRING(SS_DESANN),
00066         ENUM2STRING(SS_TAVION),
00067         ENUM2STRING(SS_DUAL),
00068         ENUM2STRING(SS_STAFF),
00069         "", 0
00070 };
00071 
00072 //Weapon and force power tables are also used in NPC parsing code and some other places.
00073 stringID_table_t WPTable[] =
00074 {
00075         "NULL",WP_NONE,
00076         ENUM2STRING(WP_NONE),
00077         // Player weapons
00078         ENUM2STRING(WP_STUN_BATON),
00079         ENUM2STRING(WP_MELEE),
00080         ENUM2STRING(WP_SABER),
00081         ENUM2STRING(WP_BRYAR_PISTOL),
00082         "WP_BLASTER_PISTOL", WP_BRYAR_PISTOL,
00083         ENUM2STRING(WP_BLASTER),
00084         ENUM2STRING(WP_DISRUPTOR),
00085         ENUM2STRING(WP_BOWCASTER),
00086         ENUM2STRING(WP_REPEATER),
00087         ENUM2STRING(WP_DEMP2),
00088         ENUM2STRING(WP_FLECHETTE),
00089         ENUM2STRING(WP_ROCKET_LAUNCHER),
00090         ENUM2STRING(WP_THERMAL),
00091         ENUM2STRING(WP_TRIP_MINE),
00092         ENUM2STRING(WP_DET_PACK),
00093         ENUM2STRING(WP_CONCUSSION),
00094         ENUM2STRING(WP_BRYAR_OLD),
00095         ENUM2STRING(WP_EMPLACED_GUN),
00096         ENUM2STRING(WP_TURRET),
00097         "", 0
00098 };
00099 
00100 stringID_table_t FPTable[] =
00101 {
00102         ENUM2STRING(FP_HEAL),
00103         ENUM2STRING(FP_LEVITATION),
00104         ENUM2STRING(FP_SPEED),
00105         ENUM2STRING(FP_PUSH),
00106         ENUM2STRING(FP_PULL),
00107         ENUM2STRING(FP_TELEPATHY),
00108         ENUM2STRING(FP_GRIP),
00109         ENUM2STRING(FP_LIGHTNING),
00110         ENUM2STRING(FP_RAGE),
00111         ENUM2STRING(FP_PROTECT),
00112         ENUM2STRING(FP_ABSORB),
00113         ENUM2STRING(FP_TEAM_HEAL),
00114         ENUM2STRING(FP_TEAM_FORCE),
00115         ENUM2STRING(FP_DRAIN),
00116         ENUM2STRING(FP_SEE),
00117         ENUM2STRING(FP_SABER_OFFENSE),
00118         ENUM2STRING(FP_SABER_DEFENSE),
00119         ENUM2STRING(FP_SABERTHROW),
00120         "",     -1
00121 };
00122 
00123 stringID_table_t HoldableTable[] =
00124 {
00125         ENUM2STRING(HI_NONE),
00126 
00127         ENUM2STRING(HI_SEEKER),
00128         ENUM2STRING(HI_SHIELD),
00129         ENUM2STRING(HI_MEDPAC),
00130         ENUM2STRING(HI_MEDPAC_BIG),
00131         ENUM2STRING(HI_BINOCULARS),
00132         ENUM2STRING(HI_SENTRY_GUN),
00133         ENUM2STRING(HI_JETPACK),
00134         ENUM2STRING(HI_HEALTHDISP),
00135         ENUM2STRING(HI_AMMODISP),
00136         ENUM2STRING(HI_EWEB),
00137         ENUM2STRING(HI_CLOAK),
00138 
00139         "", -1
00140 };
00141 
00142 stringID_table_t PowerupTable[] =
00143 {
00144         ENUM2STRING(PW_NONE),
00145         ENUM2STRING(PW_QUAD),
00146         ENUM2STRING(PW_BATTLESUIT),
00147         ENUM2STRING(PW_PULL),
00148         ENUM2STRING(PW_REDFLAG),
00149         ENUM2STRING(PW_BLUEFLAG),
00150         ENUM2STRING(PW_NEUTRALFLAG),
00151         ENUM2STRING(PW_SHIELDHIT),
00152         ENUM2STRING(PW_SPEEDBURST),
00153         ENUM2STRING(PW_DISINT_4),
00154         ENUM2STRING(PW_SPEED),
00155         ENUM2STRING(PW_CLOAKED),
00156         ENUM2STRING(PW_FORCE_ENLIGHTENED_LIGHT),
00157         ENUM2STRING(PW_FORCE_ENLIGHTENED_DARK),
00158         ENUM2STRING(PW_FORCE_BOON),
00159         ENUM2STRING(PW_YSALAMIRI),
00160 
00161         "", -1
00162 };
00163 
00164 
00165 //======================================
00166 //Parsing functions
00167 //======================================
00168 void BG_SiegeStripTabs(char *buf)
00169 {
00170         int i = 0;
00171         int i_r = 0;
00172 
00173         while (buf[i])
00174         {
00175                 if (buf[i] != SIEGECHAR_TAB)
00176                 { //not a tab, just stick it in
00177                         buf[i_r] = buf[i];
00178                 }
00179                 else
00180                 { //If it's a tab, convert it to a space.
00181                         buf[i_r] = ' ';
00182                 }
00183 
00184                 i_r++;
00185                 i++;
00186         }
00187 
00188         buf[i_r] = '\0';
00189 }
00190 
00191 int BG_SiegeGetValueGroup(char *buf, char *group, char *outbuf)
00192 {
00193         int i = 0;
00194         int j;
00195         char checkGroup[4096];
00196         qboolean isGroup;
00197         int parseGroups = 0;
00198 
00199         while (buf[i])
00200         {
00201                 if (buf[i] != ' ' && buf[i] != '{' && buf[i] != '}' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB)
00202                 { //we're on a valid character
00203                         if (buf[i] == '/' &&
00204                                 buf[i+1] == '/')
00205                         { //this is a comment, so skip over it
00206                                 while (buf[i] && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB)
00207                                 {
00208                                         i++;
00209                                 }
00210                         }
00211                         else
00212                         { //parse to the next space/endline/eos and check this value against our group value.
00213                                 j = 0;
00214 
00215                                 while (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB && buf[i] != '{' && buf[i])
00216                                 {
00217                                         if (buf[i] == '/' && buf[i+1] == '/')
00218                                         { //hit a comment, break out.
00219                                                 break;
00220                                         }
00221 
00222                                         checkGroup[j] = buf[i];
00223                                         j++;
00224                                         i++;
00225                                 }
00226                                 checkGroup[j] = 0;
00227 
00228                                 //Make sure this is a group as opposed to a globally defined value.
00229                                 if (buf[i] == '/' && buf[i+1] == '/')
00230                                 { //stopped on a comment, so first parse to the end of it.
00231                     while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
00232                                         {
00233                                                 i++;
00234                                         }
00235                                         while (buf[i] == '\n' || buf[i] == '\r')
00236                                         {
00237                                                 i++;
00238                                         }
00239                                 }
00240 
00241                                 if (!buf[i])
00242                                 {
00243                                         Com_Error(ERR_DROP, "Unexpected EOF while looking for group '%s'", group);
00244                                 }
00245 
00246                                 isGroup = qfalse;
00247 
00248                                 while (buf[i] && buf[i] == ' ' || buf[i] == SIEGECHAR_TAB || buf[i] == '\n' || buf[i] == '\r')
00249                                 { //parse to the next valid character
00250                                         i++;
00251                                 }
00252 
00253                                 if (buf[i] == '{')
00254                                 { //if the next valid character is an opening bracket, then this is indeed a group
00255                                         isGroup = qtrue;
00256                                 }
00257 
00258                                 //Is this the one we want?
00259                                 if (isGroup && !Q_stricmp(checkGroup, group))
00260                                 { //guess so. Parse until we hit the { indicating the beginning of the group.
00261                                         while (buf[i] != '{' && buf[i])
00262                                         {
00263                                                 i++;
00264                                         }
00265 
00266                                         if (buf[i])
00267                                         { //We're at the start of the group now, so parse to the closing bracket.
00268                                                 j = 0;
00269 
00270                                                 parseGroups = 0;
00271 
00272                                                 while ((buf[i] != '}' || parseGroups) && buf[i])
00273                                                 {
00274                                                         if (buf[i] == '{')
00275                                                         { //increment for the opening bracket.
00276                                                                 parseGroups++;
00277                                                         }
00278                                                         else if (buf[i] == '}')
00279                                                         { //decrement for the closing bracket
00280                                                                 parseGroups--;
00281                                                         }
00282 
00283                                                         if (parseGroups < 0)
00284                                                         { //Syntax error, I guess.
00285                                                                 Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
00286                                                         }
00287 
00288                                                         if ((buf[i] != '{' || parseGroups > 1) &&
00289                                                                 (buf[i] != '}' || parseGroups > 0))
00290                                                         { //don't put the start and end brackets for this group into the output buffer
00291                                                                 outbuf[j] = buf[i];
00292                                                                 j++;
00293                                                         }
00294 
00295                                                         if (buf[i] == '}' && !parseGroups)
00296                                                         { //Alright, we can break out now.
00297                                                                 break;
00298                                                         }
00299 
00300                                                         i++;
00301                                                 }
00302                                                 outbuf[j] = 0;
00303 
00304                                                 //Verify that we ended up on the closing bracket.
00305                                                 if (buf[i] != '}')
00306                                                 {
00307                                                         Com_Error(ERR_DROP, "Group '%s' is missing a closing bracket", group);
00308                                                 }
00309 
00310                                                 //Strip the tabs so we're friendly for value parsing.
00311                                                 BG_SiegeStripTabs(outbuf);
00312 
00313                                                 return 1; //we got it, so return 1.
00314                                         }
00315                                         else
00316                                         {
00317                                                 Com_Error(ERR_DROP, "Error parsing group in file, unexpected EOF before opening bracket while looking for group '%s'", group);
00318                                         }
00319                                 }
00320                                 else if (!isGroup)
00321                                 { //if it wasn't a group, parse to the end of the line
00322                                         while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
00323                                         {
00324                                                 i++;
00325                                         }
00326                                 }
00327                                 else
00328                                 { //this was a group but we not the one we wanted to find, so parse by it.
00329                                         parseGroups = 0;
00330 
00331                                         while (buf[i] && (buf[i] != '}' || parseGroups))
00332                                         {
00333                                                 if (buf[i] == '{')
00334                                                 {
00335                                                         parseGroups++;
00336                                                 }
00337                                                 else if (buf[i] == '}')
00338                                                 {
00339                                                         parseGroups--;
00340                                                 }
00341 
00342                                                 if (parseGroups < 0)
00343                                                 { //Syntax error, I guess.
00344                                                         Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
00345                                                 }
00346 
00347                                                 if (buf[i] == '}' && !parseGroups)
00348                                                 { //Alright, we can break out now.
00349                                                         break;
00350                                                 }
00351 
00352                                                 i++;
00353                                         }
00354 
00355                                         if (buf[i] != '}')
00356                                         {
00357                                                 Com_Error(ERR_DROP, "Found an opening bracket without a matching closing bracket while looking for group '%s'", group);
00358                                         }
00359 
00360                                         i++;
00361                                 }
00362                         }
00363                 }
00364                 else if (buf[i] == '{')
00365                 { //we're in a group that isn't the one we want, so parse to the end.
00366                         parseGroups = 0;
00367 
00368                         while (buf[i] && (buf[i] != '}' || parseGroups))
00369                         {
00370                                 if (buf[i] == '{')
00371                                 {
00372                                         parseGroups++;
00373                                 }
00374                                 else if (buf[i] == '}')
00375                                 {
00376                                         parseGroups--;
00377                                 }
00378 
00379                                 if (parseGroups < 0)
00380                                 { //Syntax error, I guess.
00381                                         Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
00382                                 }
00383 
00384                                 if (buf[i] == '}' && !parseGroups)
00385                                 { //Alright, we can break out now.
00386                                         break;
00387                                 }
00388 
00389                                 i++;
00390                         }
00391 
00392                         if (buf[i] != '}')
00393                         {
00394                                 Com_Error(ERR_DROP, "Found an opening bracket without a matching closing bracket while looking for group '%s'", group);
00395                         }
00396                 }
00397 
00398                 if (!buf[i])
00399                 {
00400                         break;
00401                 }
00402                 i++;
00403         }
00404 
00405         return 0; //guess we never found it.
00406 }
00407 
00408 int BG_SiegeGetPairedValue(char *buf, char *key, char *outbuf)
00409 {
00410         int i = 0;
00411         int j;
00412         int k;
00413         char checkKey[4096];
00414 
00415         while (buf[i])
00416         {
00417                 if (buf[i] != ' ' && buf[i] != '{' && buf[i] != '}' && buf[i] != '\n' && buf[i] != '\r')
00418                 { //we're on a valid character
00419                         if (buf[i] == '/' &&
00420                                 buf[i+1] == '/')
00421                         { //this is a comment, so skip over it
00422                                 while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
00423                                 {
00424                                         i++;
00425                                 }
00426                         }
00427                         else
00428                         { //parse to the next space/endline/eos and check this value against our key value.
00429                                 j = 0;
00430 
00431                                 while (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB && buf[i])
00432                                 {
00433                                         if (buf[i] == '/' && buf[i+1] == '/')
00434                                         { //hit a comment, break out.
00435                                                 break;
00436                                         }
00437 
00438                                         checkKey[j] = buf[i];
00439                                         j++;
00440                                         i++;
00441                                 }
00442                                 checkKey[j] = 0;
00443 
00444                                 k = i;
00445 
00446                                 while (buf[k] && (buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\r'))
00447                                 {
00448                                         k++;
00449                                 }
00450 
00451                                 if (buf[k] == '{')
00452                                 { //this is not the start of a value but rather of a group. We don't want to look in subgroups so skip over the whole thing.
00453                                         int openB = 0;
00454 
00455                                         while (buf[i] && (buf[i] != '}' || openB))
00456                                         {
00457                                                 if (buf[i] == '{')
00458                                                 {
00459                                                         openB++;
00460                                                 }
00461                                                 else if (buf[i] == '}')
00462                                                 {
00463                                                         openB--;
00464                                                 }
00465 
00466                                                 if (openB < 0)
00467                                                 {
00468                                                         Com_Error(ERR_DROP, "Unexpected closing bracket (too many) while parsing to end of group '%s'", checkKey);
00469                                                 }
00470 
00471                                                 if (buf[i] == '}' && !openB)
00472                                                 { //this is the end of the group
00473                                                         break;
00474                                                 }
00475                                                 i++;
00476                                         }
00477 
00478                                         if (buf[i] == '}')
00479                                         {
00480                                                 i++;
00481                                         }
00482                                 }
00483                                 else
00484                                 {
00485                                         //Is this the one we want?
00486                                         if (buf[i] != '/' || buf[i+1] != '/')
00487                                         { //make sure we didn't stop on a comment, if we did then this is considered an error in the file.
00488                                                 if (!Q_stricmp(checkKey, key))
00489                                                 { //guess so. Parse along to the next valid character, then put that into the output buffer and return 1.
00490                                                         while ((buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\r' || buf[i] == SIEGECHAR_TAB) && buf[i])
00491                                                         {
00492                                                                 i++;
00493                                                         }
00494 
00495                                                         if (buf[i])
00496                                                         { //We're at the start of the value now.
00497                                                                 qboolean parseToQuote = qfalse;
00498 
00499                                                                 if (buf[i] == '\"')
00500                                                                 { //if the value is in quotes, then stop at the next quote instead of ' '
00501                                                                         i++;
00502                                                                         parseToQuote = qtrue;
00503                                                                 }
00504 
00505                                                                 j = 0;
00506                                                                 while ( ((!parseToQuote && buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r') || (parseToQuote && buf[i] != '\"')) )
00507                                                                 {
00508                                                                         if (buf[i] == '/' &&
00509                                                                                 buf[i+1] == '/')
00510                                                                         { //hit a comment after the value? This isn't an ideal way to be writing things, but we'll support it anyway.
00511                                                                                 break;
00512                                                                         }
00513                                                                         outbuf[j] = buf[i];
00514                                                                         j++;
00515                                                                         i++;
00516 
00517                                                                         if (!buf[i])
00518                                                                         {
00519                                                                                 if (parseToQuote)
00520                                                                                 {
00521                                                                                         Com_Error(ERR_DROP, "Unexpected EOF while looking for endquote, error finding paired value for '%s'", key);
00522                                                                                 }
00523                                                                                 else
00524                                                                                 {
00525                                                                                         Com_Error(ERR_DROP, "Unexpected EOF while looking for space or endline, error finding paired value for '%s'", key);
00526                                                                                 }
00527                                                                         }
00528                                                                 }
00529                                                                 outbuf[j] = 0;
00530 
00531                                                                 return 1; //we got it, so return 1.
00532                                                         }
00533                                                         else
00534                                                         {
00535                                                                 Com_Error(ERR_DROP, "Error parsing file, unexpected EOF while looking for valud '%s'", key);
00536                                                         }
00537                                                 }
00538                                                 else
00539                                                 { //if that wasn't the desired key, then make sure we parse to the end of the line, so we don't mistake a value for a key
00540                                                         while (buf[i] && buf[i] != '\n')
00541                                                         {
00542                                                                 i++;
00543                                                         }
00544                                                 }
00545                                         }
00546                                         else
00547                                         {
00548                                                 Com_Error(ERR_DROP, "Error parsing file, found comment, expected value for '%s'", key);
00549                                         }
00550                                 }
00551                         }
00552                 }
00553 
00554                 if (!buf[i])
00555                 {
00556                         break;
00557                 }
00558                 i++;
00559         }
00560 
00561         return 0; //guess we never found it.
00562 }
00563 //======================================
00564 //End parsing functions
00565 //======================================
00566 
00567 
00568 //======================================
00569 //Class loading functions
00570 //======================================
00571 void BG_SiegeTranslateForcePowers(char *buf, siegeClass_t *siegeClass)
00572 {
00573         char checkPower[1024];
00574         char checkLevel[256];
00575         int l = 0;
00576         int k = 0;
00577         int j = 0;
00578         int i = 0;
00579         int parsedLevel = 0;
00580         qboolean allPowers = qfalse;
00581         qboolean noPowers = qfalse;
00582 
00583         if (!Q_stricmp(buf, "FP_ALL"))
00584         { //this is a special case, just give us all the powers on level 3
00585                 allPowers = qtrue;
00586         }
00587 
00588         if (buf[0] == '0' && !buf[1])
00589         { //no powers then
00590                 noPowers = qtrue;
00591         }
00592 
00593         //First clear out the powers, or in the allPowers case, give us all level 3.
00594         while (i < NUM_FORCE_POWERS)
00595         {
00596                 if (allPowers)
00597                 {
00598                         siegeClass->forcePowerLevels[i] = FORCE_LEVEL_3;
00599                 }
00600                 else
00601                 {
00602                         siegeClass->forcePowerLevels[i] = 0;
00603                 }
00604                 i++;
00605         }
00606 
00607         if (allPowers || noPowers)
00608         { //we're done now then.
00609                 return;
00610         }
00611 
00612         i = 0;
00613         while (buf[i])
00614         { //parse through the list which is seperated by |, and add all the weapons into a bitflag
00615                 if (buf[i] != ' ' && buf[i] != '|')
00616                 {
00617                         j = 0;
00618 
00619                         while (buf[i] && buf[i] != ' ' && buf[i] != '|' && buf[i] != ',')
00620                         {
00621                                 checkPower[j] = buf[i];
00622                                 j++;
00623                                 i++;
00624                         }
00625                         checkPower[j] = 0;
00626 
00627                         if (buf[i] == ',')
00628                         { //parse the power level
00629                                 i++;
00630                                 l = 0;
00631                                 while (buf[i] && buf[i] != ' ' && buf[i] != '|')
00632                                 {
00633                                         checkLevel[l] = buf[i];
00634                                         l++;
00635                                         i++;
00636                                 }
00637                                 checkLevel[l] = 0;
00638                                 parsedLevel = atoi(checkLevel);
00639 
00640                                 //keep sane limits on the powers
00641                                 if (parsedLevel < 0)
00642                                 {
00643                                         parsedLevel = 0;
00644                                 }
00645                                 if (parsedLevel > FORCE_LEVEL_5)
00646                                 {
00647                                         parsedLevel = FORCE_LEVEL_5;
00648                                 }
00649                         }
00650                         else
00651                         { //if it's not there, assume level 3 I guess.
00652                                 parsedLevel = 3;
00653                         }
00654 
00655                         if (checkPower[0])
00656                         { //Got the name, compare it against the weapon table strings.
00657                                 k = 0;
00658 
00659                                 if (!Q_stricmp(checkPower, "FP_JUMP"))
00660                                 { //haqery
00661                     strcpy(checkPower, "FP_LEVITATION");
00662                                 }
00663 
00664                                 while (FPTable[k].id != -1 && FPTable[k].name[0])
00665                                 {
00666                                         if (!Q_stricmp(checkPower, FPTable[k].name))
00667                                         { //found it, add the weapon into the weapons value
00668                                                 siegeClass->forcePowerLevels[k] = parsedLevel;
00669                                                 break;
00670                                         }
00671                                         k++;
00672                                 }
00673                         }
00674                 }
00675 
00676                 if (!buf[i])
00677                 {
00678                         break;
00679                 }
00680                 i++;
00681         }
00682 }
00683 
00684 //Used for the majority of generic val parsing stuff. buf should be the value string,
00685 //table should be the appropriate string/id table. If bitflag is qtrue then the
00686 //values are accumulated into a bitflag. If bitflag is qfalse then the first value
00687 //is returned as a directly corresponding id and no further parsing is done.
00688 int BG_SiegeTranslateGenericTable(char *buf, stringID_table_t *table, qboolean bitflag)
00689 {
00690         int items = 0;
00691         char checkItem[1024];
00692         int i = 0;
00693         int j = 0;
00694         int k = 0;
00695 
00696         if (buf[0] == '0' && !buf[1])
00697         { //special case, no items.
00698                 return 0;
00699         }
00700 
00701         while (buf[i])
00702         { //Using basically the same parsing method as we do for weapons and forcepowers.
00703                 if (buf[i] != ' ' && buf[i] != '|')
00704                 {
00705                         j = 0;
00706 
00707                         while (buf[i] && buf[i] != ' ' && buf[i] != '|')
00708                         {
00709                                 checkItem[j] = buf[i];
00710                                 j++;
00711                                 i++;
00712                         }
00713                         checkItem[j] = 0;
00714 
00715                         if (checkItem[0])
00716                         {
00717                                 k = 0;
00718 
00719                 while (table[k].name && table[k].name[0])
00720                                 { //go through the list and check the parsed flag name against the hardcoded names
00721                                         if (!Q_stricmp(checkItem, table[k].name))
00722                                         { //Got it, so add the value into our items value.
00723                                                 if (bitflag)
00724                                                 {
00725                                                         items |= (1 << table[k].id);
00726                                                 }
00727                                                 else
00728                                                 { //return the value directly then.
00729                                                         return table[k].id;
00730                                                 }
00731                                                 break;
00732                                         }
00733                                         k++;
00734                                 }
00735                         }
00736                 }
00737 
00738                 if (!buf[i])
00739                 {
00740                         break;
00741                 }
00742 
00743                 i++;
00744         }
00745         return items;
00746 }
00747 
00748 char *classTitles[SPC_MAX] =
00749 {
00750 "infantry",                     // SPC_INFANTRY
00751 "vanguard",                     // SPC_VANGUARD
00752 "support",                      // SPC_SUPPORT
00753 "jedi_general",         // SPC_JEDI
00754 "demolitionist",        // SPC_DEMOLITIONIST
00755 "heavy_weapons",        // SPC_HEAVY_WEAPONS
00756 };
00757 
00758 
00759 void BG_SiegeParseClassFile(const char *filename, siegeClassDesc_t *descBuffer)
00760 {
00761         fileHandle_t f;
00762         int len;
00763         int i;
00764         char classInfo[4096];
00765         char parseBuf[4096];
00766 
00767         len = trap_FS_FOpenFile(filename, &f, FS_READ);
00768 
00769         if (!f || len >= 4096)
00770         {
00771                 return;
00772         }
00773 
00774         trap_FS_Read(classInfo, len, f);
00775 
00776         trap_FS_FCloseFile(f);
00777 
00778         classInfo[len] = 0;
00779 
00780         //first get the description if we have a buffer for it
00781         if (descBuffer)
00782         {
00783                 if (!BG_SiegeGetPairedValue(classInfo, "description", descBuffer->desc))
00784                 {
00785                         strcpy(descBuffer->desc, "DESCRIPTION UNAVAILABLE");
00786                 }
00787 
00788                 //Hit this assert?  Memory has already been trashed.  Increase
00789                 //SIEGE_CLASS_DESC_LEN.
00790                 assert(strlen(descBuffer->desc) < SIEGE_CLASS_DESC_LEN);
00791         }
00792 
00793         BG_SiegeGetValueGroup(classInfo, "ClassInfo", classInfo);
00794 
00795         //Parse name
00796         if (BG_SiegeGetPairedValue(classInfo, "name", parseBuf))
00797         {
00798                 strcpy(bgSiegeClasses[bgNumSiegeClasses].name, parseBuf);
00799         }
00800         else
00801         {
00802                 Com_Error(ERR_DROP, "Siege class without name entry");
00803         }
00804 
00805         //Parse forced model
00806         if (BG_SiegeGetPairedValue(classInfo, "model", parseBuf))
00807         {
00808                 strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedModel, parseBuf);
00809         }
00810         else
00811         { //It's ok if there isn't one, it's optional.
00812                 bgSiegeClasses[bgNumSiegeClasses].forcedModel[0] = 0;
00813         }
00814 
00815         //Parse forced skin
00816         if (BG_SiegeGetPairedValue(classInfo, "skin", parseBuf))
00817         {
00818                 strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedSkin, parseBuf);
00819         }
00820         else
00821         { //It's ok if there isn't one, it's optional.
00822                 bgSiegeClasses[bgNumSiegeClasses].forcedSkin[0] = 0;
00823         }
00824 
00825         //Parse first saber
00826         if (BG_SiegeGetPairedValue(classInfo, "saber1", parseBuf))
00827         {
00828                 strcpy(bgSiegeClasses[bgNumSiegeClasses].saber1, parseBuf);
00829         }
00830         else
00831         { //It's ok if there isn't one, it's optional.
00832                 bgSiegeClasses[bgNumSiegeClasses].saber1[0] = 0;
00833         }
00834 
00835         //Parse second saber
00836         if (BG_SiegeGetPairedValue(classInfo, "saber2", parseBuf))
00837         {
00838                 strcpy(bgSiegeClasses[bgNumSiegeClasses].saber2, parseBuf);
00839         }
00840         else
00841         { //It's ok if there isn't one, it's optional.
00842                 bgSiegeClasses[bgNumSiegeClasses].saber2[0] = 0;
00843         }
00844 
00845         //Parse forced saber stance
00846         if (BG_SiegeGetPairedValue(classInfo, "saberstyle", parseBuf))
00847         {
00848                 bgSiegeClasses[bgNumSiegeClasses].saberStance = BG_SiegeTranslateGenericTable(parseBuf, StanceTable, qtrue);
00849         }
00850         else
00851         { //It's ok if there isn't one, it's optional.
00852                 bgSiegeClasses[bgNumSiegeClasses].saberStance = 0;
00853         }
00854 
00855         //Parse forced saber color
00856         if (BG_SiegeGetPairedValue(classInfo, "sabercolor", parseBuf))
00857         {
00858                 bgSiegeClasses[bgNumSiegeClasses].forcedSaberColor = atoi(parseBuf);
00859                 bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qtrue;
00860         }
00861         else
00862         { //It's ok if there isn't one, it's optional.
00863                 bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qfalse;
00864         }
00865 
00866         //Parse forced saber2 color
00867         if (BG_SiegeGetPairedValue(classInfo, "saber2color", parseBuf))
00868         {
00869                 bgSiegeClasses[bgNumSiegeClasses].forcedSaber2Color = atoi(parseBuf);
00870                 bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qtrue;
00871         }
00872         else
00873         { //It's ok if there isn't one, it's optional.
00874                 bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qfalse;
00875         }
00876 
00877         //Parse weapons
00878         if (BG_SiegeGetPairedValue(classInfo, "weapons", parseBuf))
00879         {
00880                 bgSiegeClasses[bgNumSiegeClasses].weapons = BG_SiegeTranslateGenericTable(parseBuf, WPTable, qtrue);
00881         }
00882         else
00883         {
00884                 Com_Error(ERR_DROP, "Siege class without weapons entry");
00885         }
00886 
00887         if (!(bgSiegeClasses[bgNumSiegeClasses].weapons & (1 << WP_SABER)))
00888         { //make sure it has melee if there's no saber
00889                 bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_MELEE);
00890 
00891                 //always give them this too if they are not a saber user
00892                 //bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_BRYAR_PISTOL);
00893         }
00894 
00895         //Parse forcepowers
00896         if (BG_SiegeGetPairedValue(classInfo, "forcepowers", parseBuf))
00897         {
00898                 BG_SiegeTranslateForcePowers(parseBuf, &bgSiegeClasses[bgNumSiegeClasses]);
00899         }
00900         else
00901         { //fine, clear out the powers.
00902                 i = 0;
00903                 while (i < NUM_FORCE_POWERS)
00904                 {
00905                         bgSiegeClasses[bgNumSiegeClasses].forcePowerLevels[i] = 0;
00906                         i++;
00907                 }
00908         }
00909 
00910         //Parse classflags
00911         if (BG_SiegeGetPairedValue(classInfo, "classflags", parseBuf))
00912         {
00913                 bgSiegeClasses[bgNumSiegeClasses].classflags = BG_SiegeTranslateGenericTable(parseBuf, bgSiegeClassFlagNames, qtrue);
00914         }
00915         else
00916         { //fine, we'll 0 it.
00917                 bgSiegeClasses[bgNumSiegeClasses].classflags = 0;
00918         }
00919 
00920         //Parse maxhealth
00921         if (BG_SiegeGetPairedValue(classInfo, "maxhealth", parseBuf))
00922         {
00923                 bgSiegeClasses[bgNumSiegeClasses].maxhealth = atoi(parseBuf);
00924         }
00925         else
00926         { //It's alright, just default to 100 then.
00927                 bgSiegeClasses[bgNumSiegeClasses].maxhealth = 100;
00928         }
00929 
00930         //Parse starthealth
00931         if (BG_SiegeGetPairedValue(classInfo, "starthealth", parseBuf))
00932         {
00933                 bgSiegeClasses[bgNumSiegeClasses].starthealth = atoi(parseBuf);
00934         }
00935         else
00936         { //It's alright, just default to 100 then.
00937                 bgSiegeClasses[bgNumSiegeClasses].starthealth = bgSiegeClasses[bgNumSiegeClasses].maxhealth;
00938         }
00939 
00940 
00941         //Parse startarmor
00942         if (BG_SiegeGetPairedValue(classInfo, "maxarmor", parseBuf))
00943         {
00944                 bgSiegeClasses[bgNumSiegeClasses].maxarmor = atoi(parseBuf);
00945         }
00946         else
00947         { //It's alright, just default to 0 then.
00948                 bgSiegeClasses[bgNumSiegeClasses].maxarmor = 0;
00949         }
00950 
00951         //Parse startarmor
00952         if (BG_SiegeGetPairedValue(classInfo, "startarmor", parseBuf))
00953         {
00954                 bgSiegeClasses[bgNumSiegeClasses].startarmor = atoi(parseBuf);
00955                 if (!bgSiegeClasses[bgNumSiegeClasses].maxarmor)
00956                 { //if they didn't specify a damn max armor then use this.
00957                         bgSiegeClasses[bgNumSiegeClasses].maxarmor = bgSiegeClasses[bgNumSiegeClasses].startarmor;
00958                 }
00959         }
00960         else
00961         { //default to maxarmor.
00962                 bgSiegeClasses[bgNumSiegeClasses].startarmor = bgSiegeClasses[bgNumSiegeClasses].maxarmor;
00963         }
00964 
00965         //Parse speed (this is a multiplier value)
00966         if (BG_SiegeGetPairedValue(classInfo, "speed", parseBuf))
00967         {
00968                 bgSiegeClasses[bgNumSiegeClasses].speed = atof(parseBuf);
00969         }
00970         else
00971         { //It's alright, just default to 1 then.
00972                 bgSiegeClasses[bgNumSiegeClasses].speed = 1.0f;
00973         }
00974 
00975         //Parse shader for ui to use
00976         if (BG_SiegeGetPairedValue(classInfo, "uishader", parseBuf))
00977         {
00978 #ifdef QAGAME
00979                 bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0;
00980                 memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
00981 #elif defined CGAME
00982                 bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0;
00983                 memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
00984 #else //ui
00985                 bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = trap_R_RegisterShaderNoMip(parseBuf);
00986                 memcpy(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,parseBuf,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
00987 #endif
00988         }
00989         else
00990         { //I guess this is an essential.. we don't want to render bad shaders or anything.
00991                 Com_Error(ERR_DROP, "Siege class without uishader entry");
00992         }
00993 
00994         //Parse shader for ui to use
00995         if (BG_SiegeGetPairedValue(classInfo, "class_shader", parseBuf))
00996         {
00997 #ifdef QAGAME
00998                 bgSiegeClasses[bgNumSiegeClasses].classShader = 0;
00999 #else //cgame, ui
01000                 bgSiegeClasses[bgNumSiegeClasses].classShader = trap_R_RegisterShaderNoMip(parseBuf);
01001                 assert( bgSiegeClasses[bgNumSiegeClasses].classShader );
01002                 if ( !bgSiegeClasses[bgNumSiegeClasses].classShader )
01003                 {
01004                         //Com_Error( ERR_DROP, "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name );
01005                         Com_Printf( "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name );
01006                 }
01007                 // A very hacky way to determine class . . . 
01008                 else
01009 #endif
01010                 {
01011                         // Find the base player class based on the icon name - very bad, I know.
01012                         int titleLength,i,arrayTitleLength;
01013                         char *holdBuf;
01014 
01015                         titleLength = strlen(parseBuf);
01016                         for (i=0;i<SPC_MAX;i++)
01017                         {
01018                                 // Back up 
01019                                 arrayTitleLength = strlen(classTitles[i]);
01020                                 if (arrayTitleLength>titleLength)       // Too long
01021                                 {
01022                                         break;
01023                                 }
01024 
01025                                 holdBuf = parseBuf + ( titleLength - arrayTitleLength);
01026                                 if (!strcmp(holdBuf,classTitles[i]))
01027                                 {
01028                                         bgSiegeClasses[bgNumSiegeClasses].playerClass = i;
01029                                         break;
01030                                 }
01031                         }
01032 
01033                         // In case the icon name doesn't match up
01034                         if (i>=SPC_MAX)
01035                         {
01036                                 bgSiegeClasses[bgNumSiegeClasses].playerClass = SPC_INFANTRY;
01037                         }
01038                 }
01039         }
01040         else
01041         { //No entry!  Bad bad bad
01042                 //Com_Error( ERR_DROP, "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name );
01043                 Com_Printf( "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name );
01044         }
01045 
01046         //Parse holdable items to use
01047         if (BG_SiegeGetPairedValue(classInfo, "holdables", parseBuf))
01048         {
01049                 bgSiegeClasses[bgNumSiegeClasses].invenItems = BG_SiegeTranslateGenericTable(parseBuf, HoldableTable, qtrue);
01050         }
01051         else
01052         { //Just don't start out with any then.
01053                 bgSiegeClasses[bgNumSiegeClasses].invenItems = 0;
01054         }
01055 
01056         //Parse powerups to use
01057         if (BG_SiegeGetPairedValue(classInfo, "powerups", parseBuf))
01058         {
01059                 bgSiegeClasses[bgNumSiegeClasses].powerups = BG_SiegeTranslateGenericTable(parseBuf, PowerupTable, qtrue);
01060         }
01061         else
01062         { //Just don't start out with any then.
01063                 bgSiegeClasses[bgNumSiegeClasses].powerups = 0;
01064         }
01065 
01066         //A successful read.
01067         bgNumSiegeClasses++;
01068 }
01069 
01070 // Count the number of like base classes
01071 int BG_SiegeCountBaseClass(const int team, const short classIndex)
01072 {
01073         int count = 0,i;
01074         siegeTeam_t *stm;
01075 
01076         stm = BG_SiegeFindThemeForTeam(team);
01077         if (!stm)
01078         {
01079                 return(0);
01080 
01081         }
01082 
01083         for (i=0;i<stm->numClasses;i++)
01084         {
01085 
01086                 if (stm->classes[i]->playerClass == classIndex)
01087                 {
01088                         count++;
01089                 }
01090         }
01091         return(count);
01092 }
01093 
01094 char *BG_GetUIPortraitFile(const int team, const short classIndex, const short cntIndex)
01095 {
01096         int count = 0,i;
01097         siegeTeam_t *stm;
01098 
01099         stm = BG_SiegeFindThemeForTeam(team);
01100         if (!stm)
01101         {
01102                 return(0);
01103 
01104         }
01105 
01106         // Loop through all the classes for this team
01107         for (i=0;i<stm->numClasses;i++)
01108         {
01109                 // does it match the base class?
01110                 if (stm->classes[i]->playerClass == classIndex)
01111                 {
01112                         if (count==cntIndex)
01113                         {
01114                                 return(stm->classes[i]->uiPortrait);
01115                         }
01116                         ++count;
01117                 }
01118         }
01119 
01120         return(0);
01121 }
01122 
01123 int BG_GetUIPortrait(const int team, const short classIndex, const short cntIndex)
01124 {
01125         int count = 0,i;
01126         siegeTeam_t *stm;
01127 
01128         stm = BG_SiegeFindThemeForTeam(team);
01129         if (!stm)
01130         {
01131                 return(0);
01132 
01133         }
01134 
01135         // Loop through all the classes for this team
01136         for (i=0;i<stm->numClasses;i++)
01137         {
01138                 // does it match the base class?
01139                 if (stm->classes[i]->playerClass == classIndex)
01140                 {
01141                         if (count==cntIndex)
01142                         {
01143                                 return(stm->classes[i]->uiPortraitShader);
01144                         }
01145                         ++count;
01146                 }
01147         }
01148 
01149         return(0);
01150 }
01151 
01152 // This is really getting ugly - looking to get the base class (within a class) based on the index passed in
01153 siegeClass_t *BG_GetClassOnBaseClass(const int team, const short classIndex, const short cntIndex)
01154 {
01155         int count = 0,i;
01156         siegeTeam_t *stm;
01157 
01158         stm = BG_SiegeFindThemeForTeam(team);
01159         if (!stm)
01160         {
01161                 return(0);
01162         }
01163 
01164         // Loop through all the classes for this team
01165         for (i=0;i<stm->numClasses;i++)
01166         {
01167                 // does it match the base class?
01168                 if (stm->classes[i]->playerClass == classIndex)
01169                 {
01170                         if (count==cntIndex)
01171                         {
01172                                 return(stm->classes[i]);
01173                         }
01174                         ++count;
01175                 }
01176         }
01177 
01178         return(0);
01179 }
01180 
01181 void BG_SiegeLoadClasses(siegeClassDesc_t *descBuffer)
01182 {
01183         int numFiles;
01184         int filelen;
01185         char filelist[4096];
01186         char filename[MAX_QPATH];
01187         char* fileptr;
01188         int i;
01189 
01190         bgNumSiegeClasses = 0;
01191 
01192         numFiles = trap_FS_GetFileList("ext_data/Siege/Classes", ".scl", filelist, 4096 );
01193         fileptr = filelist;
01194 
01195         for (i = 0; i < numFiles; i++, fileptr += filelen+1)
01196         {
01197                 filelen = strlen(fileptr);
01198                 strcpy(filename, "ext_data/Siege/Classes/");
01199                 strcat(filename, fileptr);
01200 
01201                 if (descBuffer)
01202                 {
01203                         BG_SiegeParseClassFile(filename, &descBuffer[i]);
01204                 }
01205                 else
01206                 {
01207                         BG_SiegeParseClassFile(filename, NULL);
01208                 }
01209         }
01210 }
01211 //======================================
01212 //End class loading functions
01213 //======================================
01214 
01215 
01216 //======================================
01217 //Team loading functions
01218 //======================================
01219 siegeClass_t *BG_SiegeFindClassByName(const char *classname)
01220 {
01221         int i = 0;
01222 
01223         while (i < bgNumSiegeClasses)
01224         {
01225                 if (!Q_stricmp(bgSiegeClasses[i].name, classname))
01226                 { //found it
01227                         return &bgSiegeClasses[i];
01228                 }
01229                 i++;
01230         }
01231 
01232         return NULL;
01233 }
01234 
01235 void BG_SiegeParseTeamFile(const char *filename)
01236 {
01237         fileHandle_t f;
01238         int len;
01239         char teamInfo[2048];
01240         char parseBuf[1024];
01241         char lookString[256];
01242         int i = 1;
01243         qboolean success = qtrue;
01244 
01245         len = trap_FS_FOpenFile(filename, &f, FS_READ);
01246 
01247         if (!f || len >= 2048)
01248         {
01249                 return;
01250         }
01251 
01252         trap_FS_Read(teamInfo, len, f);
01253 
01254         trap_FS_FCloseFile(f);
01255 
01256         teamInfo[len] = 0;
01257 
01258         if (BG_SiegeGetPairedValue(teamInfo, "name", parseBuf))
01259         {
01260                 strcpy(bgSiegeTeams[bgNumSiegeTeams].name, parseBuf);
01261         }
01262         else
01263         {
01264                 Com_Error(ERR_DROP, "Siege team with no name definition");
01265         }
01266 
01267 //I don't entirely like doing things this way but it's the easiest way.
01268 #ifdef CGAME
01269         if (BG_SiegeGetPairedValue(teamInfo, "FriendlyShader", parseBuf))
01270         {
01271                 bgSiegeTeams[bgNumSiegeTeams].friendlyShader = trap_R_RegisterShaderNoMip(parseBuf);
01272         }
01273 #else
01274         bgSiegeTeams[bgNumSiegeTeams].friendlyShader = 0;
01275 #endif
01276 
01277         bgSiegeTeams[bgNumSiegeTeams].numClasses = 0;
01278 
01279         if (BG_SiegeGetValueGroup(teamInfo, "Classes", teamInfo))
01280         {
01281                 while (success && i < MAX_SIEGE_CLASSES)
01282                 { //keep checking for group values named class# up to MAX_SIEGE_CLASSES until we can't find one.
01283                         strcpy(lookString, va("class%i", i));
01284 
01285                         success = BG_SiegeGetPairedValue(teamInfo, lookString, parseBuf);
01286 
01287                         if (!success)
01288                         {
01289                                 break;
01290                         }
01291 
01292                         bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses] = BG_SiegeFindClassByName(parseBuf);
01293 
01294                         if (!bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses])
01295                         {
01296                                 Com_Error(ERR_DROP, "Invalid class specified: '%s'", parseBuf);
01297                         }
01298 
01299                         bgSiegeTeams[bgNumSiegeTeams].numClasses++;
01300 
01301                         i++;
01302                 }
01303         }
01304 
01305         if (!bgSiegeTeams[bgNumSiegeTeams].numClasses)
01306         {
01307                 Com_Error(ERR_DROP, "Team defined with no allowable classes\n");
01308         }
01309 
01310         //If we get here then it was a success, so increment the team number
01311         bgNumSiegeTeams++;
01312 }
01313 
01314 void BG_SiegeLoadTeams(void)
01315 {
01316         int numFiles;
01317         int filelen;
01318         char filelist[4096];
01319         char filename[MAX_QPATH];
01320         char* fileptr;
01321         int i;
01322 
01323         bgNumSiegeTeams = 0;
01324 
01325         numFiles = trap_FS_GetFileList("ext_data/Siege/Teams", ".team", filelist, 4096 );
01326         fileptr = filelist;
01327 
01328         for (i = 0; i < numFiles; i++, fileptr += filelen+1)
01329         {
01330                 filelen = strlen(fileptr);
01331                 strcpy(filename, "ext_data/Siege/Teams/");
01332                 strcat(filename, fileptr);
01333                 BG_SiegeParseTeamFile(filename);
01334         }
01335 }
01336 //======================================
01337 //End team loading functions
01338 //======================================
01339 
01340 
01341 //======================================
01342 //Misc/utility functions
01343 //======================================
01344 siegeTeam_t *BG_SiegeFindThemeForTeam(int team)
01345 {
01346         if (team == SIEGETEAM_TEAM1)
01347         {
01348                 return team1Theme;
01349         }
01350         else if (team == SIEGETEAM_TEAM2)
01351         {
01352                 return team2Theme;
01353         }
01354 
01355     return NULL;
01356 }
01357 
01358 #ifndef UI_EXPORTS //only for game/cgame
01359 //precache all the sabers for the active classes for the team
01360 extern qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber ); //bg_saberLoad.cpp
01361 extern int BG_ModelCache(const char *modelName, const char *skinName); //bg_misc.c
01362 
01363 void BG_PrecacheSabersForSiegeTeam(int team)
01364 {
01365         siegeTeam_t *t;
01366         saberInfo_t saber;
01367         char *saberName;
01368         int sNum;
01369 
01370         t = BG_SiegeFindThemeForTeam(team);
01371 
01372         if (t)
01373         {
01374                 int i = 0;
01375 
01376                 while (i < t->numClasses)
01377                 {
01378                         sNum = 0;
01379 
01380                         while (sNum < MAX_SABERS)
01381                         {
01382                                 switch (sNum)
01383                                 {
01384                                 case 0:
01385                                         saberName = &t->classes[i]->saber1[0];
01386                                         break;
01387                                 case 1:
01388                                         saberName = &t->classes[i]->saber2[0];
01389                                         break;
01390                                 default:
01391                                         saberName = NULL;
01392                                         break;
01393                                 }
01394 
01395                                 if (saberName && saberName[0])
01396                                 {
01397                                         WP_SaberParseParms(saberName, &saber);
01398                                         if (!Q_stricmp(saberName, saber.name))
01399                                         { //found the matching saber
01400                                                 if (saber.model[0])
01401                                                 {
01402                                                         BG_ModelCache(saber.model, NULL);
01403                                                 }
01404                                         }
01405                                 }
01406 
01407                                 sNum++;
01408                         }
01409 
01410                         i++;
01411                 }
01412         }
01413 }
01414 #endif
01415 
01416 qboolean BG_SiegeCheckClassLegality(int team, char *classname)
01417 {
01418         siegeTeam_t **teamPtr = NULL;
01419         int i = 0;
01420 
01421         if (team == SIEGETEAM_TEAM1)
01422         {
01423                 teamPtr = &team1Theme;
01424         }
01425         else if (team == SIEGETEAM_TEAM2)
01426         {
01427                 teamPtr = &team2Theme;
01428         }
01429         else
01430         { //spectator? Whatever, you're legal then.
01431                 return qtrue;
01432         }
01433 
01434         if (!teamPtr || !(*teamPtr))
01435         { //Well, guess the class is ok, seeing as there is no team theme to begin with.
01436                 return qtrue;
01437         }
01438 
01439         //See if the class is listed on the team
01440         while (i < (*teamPtr)->numClasses)
01441         {
01442                 if (!Q_stricmp(classname, (*teamPtr)->classes[i]->name))
01443                 { //found it, so it's alright
01444                         return qtrue;
01445                 }
01446                 i++;
01447         }
01448 
01449         //Didn't find it, so copy the name of the first valid class over it.
01450         strcpy(classname, (*teamPtr)->classes[0]->name);
01451 
01452         return qfalse;
01453 }
01454 
01455 siegeTeam_t *BG_SiegeFindTeamForTheme(char *themeName)
01456 {
01457         int i = 0;
01458 
01459         while (i < bgNumSiegeTeams)
01460         {
01461                 if (bgSiegeTeams[i].name &&
01462                         !Q_stricmp(bgSiegeTeams[i].name, themeName))
01463                 { //this is what we're looking for
01464                         return &bgSiegeTeams[i];
01465                 }
01466 
01467                 i++;
01468         }
01469 
01470         return NULL;
01471 }
01472 
01473 void BG_SiegeSetTeamTheme(int team, char *themeName)
01474 {
01475         siegeTeam_t **teamPtr = NULL;
01476 
01477         if (team == SIEGETEAM_TEAM1)
01478         {
01479                 teamPtr = &team1Theme;
01480         }
01481         else
01482         {
01483                 teamPtr = &team2Theme;
01484         }
01485 
01486         (*teamPtr) = BG_SiegeFindTeamForTheme(themeName);
01487 }
01488 
01489 int BG_SiegeFindClassIndexByName(const char *classname)
01490 {
01491         int i = 0;
01492 
01493         while (i < bgNumSiegeClasses)
01494         {
01495                 if (!Q_stricmp(bgSiegeClasses[i].name, classname))
01496                 { //found it
01497                         return i;
01498                 }
01499                 i++;
01500         }
01501 
01502         return -1;
01503 }
01504 //======================================
01505 //End misc/utility functions
01506 //======================================
01507 
01508 #include "../namespace_end.h"