codemp/game/bg_saberLoad.c

Go to the documentation of this file.
00001 //bg_saberLoad.c
00002 #include "q_shared.h"
00003 #include "bg_public.h"
00004 #include "bg_local.h"
00005 #include "w_saber.h"
00006 
00007 extern stringID_table_t animTable [MAX_ANIMATIONS+1];
00008 
00009 //Could use strap stuff but I don't particularly care at the moment anyway.
00010 #include "../namespace_begin.h"
00011 extern int      trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
00012 extern void     trap_FS_Read( void *buffer, int len, fileHandle_t f );
00013 extern void     trap_FS_Write( const void *buffer, int len, fileHandle_t f );
00014 extern void     trap_FS_FCloseFile( fileHandle_t f );
00015 extern int      trap_FS_GetFileList(  const char *path, const char *extension, char *listbuf, int bufsize );
00016 extern qhandle_t trap_R_RegisterSkin( const char *name );
00017 #include "../namespace_end.h"
00018 
00019 
00020 #ifdef QAGAME
00021 extern int G_SoundIndex( const char *name );
00022 #elif defined CGAME
00023 #include "../namespace_begin.h"
00024 sfxHandle_t trap_S_RegisterSound( const char *sample);
00025 qhandle_t       trap_R_RegisterShader( const char *name );                      // returns all white if not found
00026 int     trap_FX_RegisterEffect(const char *file);
00027 #include "../namespace_end.h"
00028 #endif
00029 
00030 #include "../namespace_begin.h"
00031 
00032 int BG_SoundIndex(char *sound)
00033 {
00034 #ifdef QAGAME
00035         return G_SoundIndex(sound);
00036 #elif defined CGAME
00037         return trap_S_RegisterSound(sound);
00038 #endif
00039 }
00040 
00041 extern stringID_table_t FPTable[];
00042 
00043 #define MAX_SABER_DATA_SIZE 0x80000
00044 static char SaberParms[MAX_SABER_DATA_SIZE];
00045 
00046 stringID_table_t SaberTable[] =
00047 {
00048         ENUM2STRING(SABER_NONE),
00049         ENUM2STRING(SABER_SINGLE),
00050         ENUM2STRING(SABER_STAFF),
00051         ENUM2STRING(SABER_BROAD),
00052         ENUM2STRING(SABER_PRONG),
00053         ENUM2STRING(SABER_DAGGER),
00054         ENUM2STRING(SABER_ARC),
00055         ENUM2STRING(SABER_SAI),
00056         ENUM2STRING(SABER_CLAW),
00057         ENUM2STRING(SABER_LANCE),
00058         ENUM2STRING(SABER_STAR),
00059         ENUM2STRING(SABER_TRIDENT),
00060         "",     -1
00061 };
00062 
00063 stringID_table_t SaberMoveTable[] =
00064 {
00065         ENUM2STRING(LS_NONE),
00066         // Attacks
00067         ENUM2STRING(LS_A_TL2BR),
00068         ENUM2STRING(LS_A_L2R),
00069         ENUM2STRING(LS_A_BL2TR),
00070         ENUM2STRING(LS_A_BR2TL),
00071         ENUM2STRING(LS_A_R2L),
00072         ENUM2STRING(LS_A_TR2BL),
00073         ENUM2STRING(LS_A_T2B),
00074         ENUM2STRING(LS_A_BACKSTAB),
00075         ENUM2STRING(LS_A_BACK),
00076         ENUM2STRING(LS_A_BACK_CR),
00077         ENUM2STRING(LS_ROLL_STAB),
00078         ENUM2STRING(LS_A_LUNGE),
00079         ENUM2STRING(LS_A_JUMP_T__B_),
00080         ENUM2STRING(LS_A_FLIP_STAB),
00081         ENUM2STRING(LS_A_FLIP_SLASH),
00082         ENUM2STRING(LS_JUMPATTACK_DUAL),
00083         ENUM2STRING(LS_JUMPATTACK_ARIAL_LEFT),
00084         ENUM2STRING(LS_JUMPATTACK_ARIAL_RIGHT),
00085         ENUM2STRING(LS_JUMPATTACK_CART_LEFT),
00086         ENUM2STRING(LS_JUMPATTACK_CART_RIGHT),
00087         ENUM2STRING(LS_JUMPATTACK_STAFF_LEFT),
00088         ENUM2STRING(LS_JUMPATTACK_STAFF_RIGHT),
00089         ENUM2STRING(LS_BUTTERFLY_LEFT),
00090         ENUM2STRING(LS_BUTTERFLY_RIGHT),
00091         ENUM2STRING(LS_A_BACKFLIP_ATK),
00092         ENUM2STRING(LS_SPINATTACK_DUAL),
00093         ENUM2STRING(LS_SPINATTACK),
00094         ENUM2STRING(LS_LEAP_ATTACK),
00095         ENUM2STRING(LS_SWOOP_ATTACK_RIGHT),
00096         ENUM2STRING(LS_SWOOP_ATTACK_LEFT),
00097         ENUM2STRING(LS_TAUNTAUN_ATTACK_RIGHT),
00098         ENUM2STRING(LS_TAUNTAUN_ATTACK_LEFT),
00099         ENUM2STRING(LS_KICK_F),
00100         ENUM2STRING(LS_KICK_B),
00101         ENUM2STRING(LS_KICK_R),
00102         ENUM2STRING(LS_KICK_L),
00103         ENUM2STRING(LS_KICK_S),
00104         ENUM2STRING(LS_KICK_BF),
00105         ENUM2STRING(LS_KICK_RL),
00106         ENUM2STRING(LS_KICK_F_AIR),
00107         ENUM2STRING(LS_KICK_B_AIR),
00108         ENUM2STRING(LS_KICK_R_AIR),
00109         ENUM2STRING(LS_KICK_L_AIR),
00110         ENUM2STRING(LS_STABDOWN),
00111         ENUM2STRING(LS_STABDOWN_STAFF),
00112         ENUM2STRING(LS_STABDOWN_DUAL),
00113         ENUM2STRING(LS_DUAL_SPIN_PROTECT),
00114         ENUM2STRING(LS_STAFF_SOULCAL),
00115         ENUM2STRING(LS_A1_SPECIAL),
00116         ENUM2STRING(LS_A2_SPECIAL),
00117         ENUM2STRING(LS_A3_SPECIAL),
00118         ENUM2STRING(LS_UPSIDE_DOWN_ATTACK),
00119         ENUM2STRING(LS_PULL_ATTACK_STAB),
00120         ENUM2STRING(LS_PULL_ATTACK_SWING),
00121         ENUM2STRING(LS_SPINATTACK_ALORA),
00122         ENUM2STRING(LS_DUAL_FB),
00123         ENUM2STRING(LS_DUAL_LR),
00124         ENUM2STRING(LS_HILT_BASH),
00125         "",     -1
00126 };
00127 
00128 //Also used in npc code
00129 qboolean BG_ParseLiteral( const char **data, const char *string ) 
00130 {
00131         const char      *token;
00132 
00133         token = COM_ParseExt( data, qtrue );
00134         if ( token[0] == 0 ) 
00135         {
00136                 Com_Printf( "unexpected EOF\n" );
00137                 return qtrue;
00138         }
00139 
00140         if ( Q_stricmp( token, string ) ) 
00141         {
00142                 Com_Printf( "required string '%s' missing\n", string );
00143                 return qtrue;
00144         }
00145 
00146         return qfalse;
00147 }
00148 
00149 saber_colors_t TranslateSaberColor( const char *name ) 
00150 {
00151         if ( !Q_stricmp( name, "red" ) ) 
00152         {
00153                 return SABER_RED;
00154         }
00155         if ( !Q_stricmp( name, "orange" ) ) 
00156         {
00157                 return SABER_ORANGE;
00158         }
00159         if ( !Q_stricmp( name, "yellow" ) ) 
00160         {
00161                 return SABER_YELLOW;
00162         }
00163         if ( !Q_stricmp( name, "green" ) ) 
00164         {
00165                 return SABER_GREEN;
00166         }
00167         if ( !Q_stricmp( name, "blue" ) ) 
00168         {
00169                 return SABER_BLUE;
00170         }
00171         if ( !Q_stricmp( name, "purple" ) ) 
00172         {
00173                 return SABER_PURPLE;
00174         }
00175         if ( !Q_stricmp( name, "random" ) ) 
00176         {
00177                 return ((saber_colors_t)(Q_irand( SABER_ORANGE, SABER_PURPLE )));
00178         }
00179         return SABER_BLUE;
00180 }
00181 
00182 saber_styles_t TranslateSaberStyle( const char *name ) 
00183 {
00184         if ( !Q_stricmp( name, "fast" ) ) 
00185         {
00186                 return SS_FAST;
00187         }
00188         if ( !Q_stricmp( name, "medium" ) ) 
00189         {
00190                 return SS_MEDIUM;
00191         }
00192         if ( !Q_stricmp( name, "strong" ) ) 
00193         {
00194                 return SS_STRONG;
00195         }
00196         if ( !Q_stricmp( name, "desann" ) ) 
00197         {
00198                 return SS_DESANN;
00199         }
00200         if ( !Q_stricmp( name, "tavion" ) ) 
00201         {
00202                 return SS_TAVION;
00203         }
00204         if ( !Q_stricmp( name, "dual" ) ) 
00205         {
00206                 return SS_DUAL;
00207         }
00208         if ( !Q_stricmp( name, "staff" ) ) 
00209         {
00210                 return SS_STAFF;
00211         }
00212         return SS_NONE;
00213 }
00214 
00215 qboolean WP_SaberBladeUseSecondBladeStyle( saberInfo_t *saber, int bladeNum )
00216 {
00217         if ( saber )
00218         {
00219                 if ( saber->bladeStyle2Start > 0 )
00220                 {
00221                         if ( bladeNum >= saber->bladeStyle2Start )
00222                         {
00223                                 return qtrue;
00224                         }
00225                 }
00226         }
00227         return qfalse;
00228 }
00229 
00230 qboolean WP_SaberBladeDoTransitionDamage( saberInfo_t *saber, int bladeNum )
00231 {
00232         if ( !WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
00233                 && (saber->saberFlags2&SFL2_TRANSITION_DAMAGE) )
00234         {//use first blade style for this blade
00235                 return qtrue;
00236         }
00237         else if ( WP_SaberBladeUseSecondBladeStyle( saber, bladeNum )
00238                 && (saber->saberFlags2&SFL2_TRANSITION_DAMAGE2) )
00239         {//use second blade style for this blade
00240                 return qtrue;
00241         }
00242         return qfalse;
00243 }
00244 
00245 qboolean WP_UseFirstValidSaberStyle( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int *saberAnimLevel )
00246 {
00247         qboolean styleInvalid = qfalse;
00248         qboolean saber1Active;
00249         qboolean saber2Active;
00250         qboolean dualSabers = qfalse;
00251         int     validStyles = 0, styleNum;
00252 
00253         if ( saber2 && saber2->model && saber2->model[0] )
00254         {
00255                 dualSabers = qtrue;
00256         }
00257 
00258         if ( dualSabers )
00259         {//dual
00260                 if ( saberHolstered > 1 )
00261                 {
00262                         saber1Active = saber2Active = qfalse;
00263                 }
00264                 else if ( saberHolstered > 0 )
00265                 {
00266                         saber1Active = qtrue;
00267                         saber2Active = qfalse;
00268                 }
00269                 else
00270                 {
00271                         saber1Active = saber2Active = qtrue;
00272                 }
00273         }
00274         else
00275         {
00276                 saber2Active = qfalse;
00277                 if ( !saber1
00278                         || !saber1->model
00279                         || !saber1->model[0] )
00280                 {
00281                         saber1Active = qfalse;
00282                 }
00283                 else if ( saber1->numBlades > 1 )
00284                 {//staff
00285                         if ( saberHolstered > 1 )
00286                         {
00287                                 saber1Active = qfalse;
00288                         }
00289                         else
00290                         {
00291                                 saber1Active = qtrue;
00292                         }
00293                 }
00294                 else
00295                 {//single
00296                         if ( saberHolstered )
00297                         {
00298                                 saber1Active = qfalse;
00299                         }
00300                         else
00301                         {
00302                                 saber1Active = qtrue;
00303                         }
00304                 }
00305         }
00306 
00307         //initially, all styles are valid
00308         for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
00309         {
00310                 validStyles |= (1<<styleNum);
00311         }
00312 
00313         if ( saber1Active
00314                 && saber1
00315                 && saber1->model
00316                 && saber1->model[0]
00317                 && saber1->stylesForbidden )
00318         {
00319                 if ( (saber1->stylesForbidden&(1<<*saberAnimLevel)) )
00320                 {//not a valid style for first saber!
00321                         styleInvalid = qtrue;
00322                         validStyles &= ~saber1->stylesForbidden;
00323                 }
00324         }
00325         if ( dualSabers )
00326         {//check second saber, too
00327                 if ( saber2Active
00328                         && saber2->stylesForbidden )
00329                 {
00330                         if ( (saber2->stylesForbidden&(1<<*saberAnimLevel)) )
00331                         {//not a valid style for second saber!
00332                                 styleInvalid = qtrue;
00333                                 //only the ones both sabers allow is valid
00334                                 validStyles &= ~saber2->stylesForbidden;
00335                         }
00336                 }
00337         }
00338         if ( styleInvalid && validStyles )
00339         {//using an invalid style and have at least one valid style to use, so switch to it
00340                 int styleNum;
00341                 for ( styleNum = SS_FAST; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
00342                 {
00343                         if ( (validStyles&(1<<styleNum)) )
00344                         {
00345                                 *saberAnimLevel = styleNum;
00346                                 return qtrue;
00347                         }
00348                 }
00349         }
00350         return qfalse;
00351 }
00352 
00353 qboolean WP_SaberStyleValidForSaber( saberInfo_t *saber1, saberInfo_t *saber2, int saberHolstered, int saberAnimLevel )
00354 {
00355         qboolean saber1Active;
00356         qboolean saber2Active;
00357         qboolean dualSabers = qfalse;
00358 
00359         if ( saber2 && saber2->model && saber2->model[0] )
00360         {
00361                 dualSabers = qtrue;
00362         }
00363 
00364         if ( dualSabers )
00365         {//dual
00366                 if ( saberHolstered > 1 )
00367                 {
00368                         saber1Active = saber2Active = qfalse;
00369                 }
00370                 else if ( saberHolstered > 0 )
00371                 {
00372                         saber1Active = qtrue;
00373                         saber2Active = qfalse;
00374                 }
00375                 else
00376                 {
00377                         saber1Active = saber2Active = qtrue;
00378                 }
00379         }
00380         else
00381         {
00382                 saber2Active = qfalse;
00383                 if ( !saber1
00384                         || !saber1->model
00385                         || !saber1->model[0] )
00386                 {
00387                         saber1Active = qfalse;
00388                 }
00389                 else if ( saber1->numBlades > 1 )
00390                 {//staff
00391                         if ( saberHolstered > 1 )
00392                         {
00393                                 saber1Active = qfalse;
00394                         }
00395                         else
00396                         {
00397                                 saber1Active = qtrue;
00398                         }
00399                 }
00400                 else
00401                 {//single
00402                         if ( saberHolstered )
00403                         {
00404                                 saber1Active = qfalse;
00405                         }
00406                         else
00407                         {
00408                                 saber1Active = qtrue;
00409                         }
00410                 }
00411         }
00412 
00413         if ( saber1Active
00414                 && saber1
00415                 && saber1->model
00416                 && saber1->model[0]
00417                 && saber1->stylesForbidden )
00418         {
00419                 if ( (saber1->stylesForbidden&(1<<saberAnimLevel)) )
00420                 {//not a valid style for first saber!
00421                         return qfalse;
00422                 }
00423         }
00424         if ( dualSabers
00425                 && saber2Active
00426                 && saber2
00427                 && saber2->model
00428                 && saber2->model[0] )
00429         {
00430                 if ( saber2->stylesForbidden )
00431                 {//check second saber, too
00432                         if ( (saber2->stylesForbidden&(1<<saberAnimLevel)) )
00433                         {//not a valid style for second saber!
00434                                 return qfalse;
00435                         }
00436                 }
00437                 //now: if using dual sabers, only dual and tavion (if given with this saber) are allowed
00438                 if ( saberAnimLevel != SS_DUAL )
00439                 {//dual is okay
00440                         if ( saberAnimLevel != SS_TAVION )
00441                         {//tavion might be okay, all others are not
00442                                 return qfalse;
00443                         }
00444                         else
00445                         {//see if "tavion" style is okay
00446                                 if ( saber1Active
00447                                         && saber1
00448                                         && saber1->model
00449                                         && saber1->model[0]
00450                                         && (saber1->stylesLearned&(1<<SS_TAVION)) )
00451                                 {//okay to use tavion style, first saber gave it to us
00452                                 }
00453                                 else if ( (saber2->stylesLearned&(1<<SS_TAVION)) )
00454                                 {//okay to use tavion style, second saber gave it to us
00455                                 }
00456                                 else
00457                                 {//tavion style is not allowed because neither of the sabers we're using gave it to us (I know, doesn't quite make sense, but...)
00458                                         return qfalse;
00459                                 }
00460                         }
00461                 }
00462         }
00463         return qtrue;
00464 }
00465 
00466 qboolean WP_SaberCanTurnOffSomeBlades( saberInfo_t *saber )
00467 {
00468         if ( saber->bladeStyle2Start > 0
00469                 && saber->numBlades > saber->bladeStyle2Start )
00470         {
00471                 if ( (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE)
00472                         && (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE2) )
00473                 {//all blades are always on
00474                         return qfalse;
00475                 }
00476         }
00477         else
00478         {
00479                 if ( (saber->saberFlags2&SFL2_NO_MANUAL_DEACTIVATE) )
00480                 {//all blades are always on
00481                         return qfalse;
00482                 }
00483         }
00484         //you can turn some off
00485         return qtrue;
00486 }
00487 
00488 void WP_SaberSetDefaults( saberInfo_t *saber )
00489 {
00490         int i;
00491 
00492         //Set defaults so that, if it fails, there's at least something there
00493         for ( i = 0; i < MAX_BLADES; i++ )
00494         {
00495                 saber->blade[i].color = SABER_RED;
00496                 saber->blade[i].radius = SABER_RADIUS_STANDARD;
00497                 saber->blade[i].lengthMax = 32;
00498         }
00499 
00500         strcpy(saber->name, "default");
00501         strcpy(saber->fullName, "lightsaber");
00502         strcpy(saber->model, "models/weapons2/saber_reborn/saber_w.glm");
00503         saber->skin = 0;
00504         saber->soundOn = BG_SoundIndex( "sound/weapons/saber/enemy_saber_on.wav" );
00505         saber->soundLoop = BG_SoundIndex( "sound/weapons/saber/saberhum3.wav" );
00506         saber->soundOff = BG_SoundIndex( "sound/weapons/saber/enemy_saber_off.wav" );
00507         saber->numBlades = 1;
00508         saber->type = SABER_SINGLE;
00509         saber->stylesLearned = 0;
00510         saber->stylesForbidden = 0;//allow all styles
00511         saber->maxChain = 0;//0 = use default behavior
00512         saber->forceRestrictions = 0;
00513         saber->lockBonus = 0;
00514         saber->parryBonus = 0;
00515         saber->breakParryBonus = 0;
00516         saber->breakParryBonus2 = 0;
00517         saber->disarmBonus = 0;
00518         saber->disarmBonus2 = 0;
00519         saber->singleBladeStyle = SS_NONE;//makes it so that you use a different style if you only have the first blade active
00520 //      saber->brokenSaber1 = NULL;//if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your right hand
00521 //      saber->brokenSaber2 = NULL;//if saber is actually hit by another saber, it can be cut in half/broken and will be replaced with this saber in your left hand
00522 //===NEW========================================================================================
00523         //done in cgame (client-side code)
00524         saber->saberFlags = 0;                                  //see all the SFL_ flags
00525         saber->saberFlags2 = 0;                                 //see all the SFL2_ flags
00526 
00527         saber->spinSound = 0;                                   //none - if set, plays this sound as it spins when thrown
00528         saber->swingSound[0] = 0;                               //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
00529         saber->swingSound[1] = 0;                               //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
00530         saber->swingSound[2] = 0;                               //none - if set, plays one of these 3 sounds when swung during an attack - NOTE: must provide all 3!!!
00531 
00532         //done in game (server-side code)
00533         saber->moveSpeedScale = 1.0f;                           //1.0 - you move faster/slower when using this saber
00534         saber->animSpeedScale = 1.0f;                           //1.0 - plays normal attack animations faster/slower
00535 
00536         saber->kataMove = LS_INVALID;                           //LS_INVALID - if set, player will execute this move when they press both attack buttons at the same time 
00537         saber->lungeAtkMove = LS_INVALID;                       //LS_INVALID - if set, player will execute this move when they crouch+fwd+attack 
00538         saber->jumpAtkUpMove = LS_INVALID;                      //LS_INVALID - if set, player will execute this move when they jump+attack 
00539         saber->jumpAtkFwdMove = LS_INVALID;                     //LS_INVALID - if set, player will execute this move when they jump+fwd+attack 
00540         saber->jumpAtkBackMove = LS_INVALID;            //LS_INVALID - if set, player will execute this move when they jump+back+attack
00541         saber->jumpAtkRightMove = LS_INVALID;           //LS_INVALID - if set, player will execute this move when they jump+rightattack
00542         saber->jumpAtkLeftMove = LS_INVALID;            //LS_INVALID - if set, player will execute this move when they jump+left+attack
00543         saber->readyAnim = -1;                                          //-1 - anim to use when standing idle
00544         saber->drawAnim = -1;                                           //-1 - anim to use when drawing weapon
00545         saber->putawayAnim = -1;                                        //-1 - anim to use when putting weapon away
00546         saber->tauntAnim = -1;                                          //-1 - anim to use when hit "taunt"
00547         saber->bowAnim = -1;                                            //-1 - anim to use when hit "bow"
00548         saber->meditateAnim = -1;                                       //-1 - anim to use when hit "meditate"
00549         saber->flourishAnim = -1;                                       //-1 - anim to use when hit "flourish"
00550         saber->gloatAnim = -1;                                          //-1 - anim to use when hit "gloat"
00551 
00552         //***NOTE: you can only have a maximum of 2 "styles" of blades, so this next value, "bladeStyle2Start" is the number of the first blade to use these value on... all blades before this use the normal values above, all blades at and after this number use the secondary values below***
00553         saber->bladeStyle2Start = 0;                    //0 - if set, blades from this number and higher use the following values (otherwise, they use the normal values already set)
00554         
00555         //***The following can be different for the extra blades - not setting them individually defaults them to the value for the whole saber (and first blade)***
00556 
00557         //===PRIMARY BLADES=====================
00558         //done in cgame (client-side code)
00559         saber->trailStyle = 0;                                  //0 - default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
00560         saber->g2MarksShader = 0;                               //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
00561         saber->g2WeaponMarkShader = 0;                  //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
00562         //saber->bladeShader = 0;                               //none - if set, overrides the shader used for the saber blade?
00563         //saber->trailShader = 0;                               //none - if set, overrides the shader used for the saber trail?
00564         saber->hitSound[0] = 0;                                 //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00565         saber->hitSound[1] = 0;                                 //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00566         saber->hitSound[2] = 0;                                 //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00567         saber->blockSound[0] = 0;                               //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00568         saber->blockSound[1] = 0;                               //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00569         saber->blockSound[2] = 0;                               //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00570         saber->bounceSound[0] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00571         saber->bounceSound[1] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00572         saber->bounceSound[2] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00573         saber->blockEffect = 0;                                 //none - if set, plays this effect when the saber/sword hits another saber/sword (instead of "saber/saber_block.efx")
00574         saber->hitPersonEffect = 0;                             //none - if set, plays this effect when the saber/sword hits a person (instead of "saber/blood_sparks_mp.efx")
00575         saber->hitOtherEffect = 0;                              //none - if set, plays this effect when the saber/sword hits something else damagable (instead of "saber/saber_cut.efx")
00576         saber->bladeEffect = 0;                                 //none - if set, plays this effect at the blade tag
00577 
00578         //done in game (server-side code)
00579         saber->knockbackScale = 0;                              //0 - if non-zero, uses damage done to calculate an appropriate amount of knockback
00580         saber->damageScale = 1.0f;                              //1 - scale up or down the damage done by the saber
00581         saber->splashRadius = 0.0f;                             //0 - radius of splashDamage
00582         saber->splashDamage = 0;                                //0 - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
00583         saber->splashKnockback = 0.0f;                  //0 - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
00584 
00585         //===SECONDARY BLADES===================
00586         //done in cgame (client-side code)
00587         saber->trailStyle2 = 0;                                 //0 - default (0) is normal, 1 is a motion blur and 2 is no trail at all (good for real-sword type mods)
00588         saber->g2MarksShader2 = 0;                              //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
00589         saber->g2WeaponMarkShader2 = 0;                 //none - if set, the game will use this shader for marks on enemies instead of the default "gfx/damage/saberglowmark"
00590         //saber->bladeShader = 0;                               //none - if set, overrides the shader used for the saber blade?
00591         //saber->trailShader = 0;                               //none - if set, overrides the shader used for the saber trail?
00592         saber->hit2Sound[0] = 0;                                        //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00593         saber->hit2Sound[1] = 0;                                        //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00594         saber->hit2Sound[2] = 0;                                        //none - if set, plays one of these 3 sounds when saber hits a person - NOTE: must provide all 3!!!
00595         saber->block2Sound[0] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00596         saber->block2Sound[1] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00597         saber->block2Sound[2] = 0;                              //none - if set, plays one of these 3 sounds when saber/sword hits another saber/sword - NOTE: must provide all 3!!!
00598         saber->bounce2Sound[0] = 0;                             //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00599         saber->bounce2Sound[1] = 0;                             //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00600         saber->bounce2Sound[2] = 0;                             //none - if set, plays one of these 3 sounds when saber/sword hits a wall and bounces off (must set bounceOnWall to 1 to use these sounds) - NOTE: must provide all 3!!!
00601         saber->blockEffect2 = 0;                                        //none - if set, plays this effect when the saber/sword hits another saber/sword (instead of "saber/saber_block.efx")
00602         saber->hitPersonEffect2 = 0;                            //none - if set, plays this effect when the saber/sword hits a person (instead of "saber/blood_sparks_mp.efx")
00603         saber->hitOtherEffect2 = 0;                             //none - if set, plays this effect when the saber/sword hits something else damagable (instead of "saber/saber_cut.efx")
00604         saber->bladeEffect2 = 0;                                //none - if set, plays this effect at the blade tag
00605 
00606         //done in game (server-side code)
00607         saber->knockbackScale2 = 0;                             //0 - if non-zero, uses damage done to calculate an appropriate amount of knockback
00608         saber->damageScale2 = 1.0f;                             //1 - scale up or down the damage done by the saber
00609         saber->splashRadius2 = 0.0f;                            //0 - radius of splashDamage
00610         saber->splashDamage2 = 0;                               //0 - amount of splashDamage, 100% at a distance of 0, 0% at a distance = splashRadius
00611         saber->splashKnockback2 = 0.0f;                 //0 - amount of splashKnockback, 100% at a distance of 0, 0% at a distance = splashRadius
00612 //=========================================================================================================================================
00613 }
00614 
00615 #define DEFAULT_SABER "Kyle"
00616 
00617 qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber ) 
00618 {
00619         const char      *token;
00620         const char      *value;
00621         const char      *p;
00622         char    useSaber[1024];
00623         float   f;
00624         int             n;
00625         qboolean        triedDefault = qfalse;
00626         int saberMove = LS_INVALID;
00627         int     anim = -1;
00628         
00629         if ( !saber ) 
00630         {
00631                 return qfalse;
00632         }
00633         
00634         //Set defaults so that, if it fails, there's at least something there
00635         WP_SaberSetDefaults( saber );
00636 
00637         if ( !SaberName || !SaberName[0] ) 
00638         {
00639                 strcpy(useSaber, DEFAULT_SABER); //default
00640                 triedDefault = qtrue;
00641         }
00642         else
00643         {
00644                 strcpy(useSaber, SaberName);
00645         }
00646 
00647         //try to parse it out
00648         p = SaberParms;
00649         COM_BeginParseSession("saberinfo");
00650 
00651         // look for the right saber
00652         while ( p )
00653         {
00654                 token = COM_ParseExt( &p, qtrue );
00655                 if ( token[0] == 0 )
00656                 {
00657                         if (!triedDefault)
00658                         { //fall back to default and restart, should always be there
00659                                 p = SaberParms;
00660                                 COM_BeginParseSession("saberinfo");
00661                                 strcpy(useSaber, DEFAULT_SABER);
00662                                 triedDefault = qtrue;
00663                         }
00664                         else
00665                         {
00666                                 return qfalse;
00667                         }
00668                 }
00669 
00670                 if ( !Q_stricmp( token, useSaber ) ) 
00671                 {
00672                         break;
00673                 }
00674 
00675                 SkipBracedSection( &p );
00676         }
00677         if ( !p ) 
00678         { //even the default saber isn't found?
00679                 return qfalse;
00680         }
00681 
00682         //got the name we're using for sure
00683         strcpy(saber->name, useSaber);
00684 
00685         if ( BG_ParseLiteral( &p, "{" ) ) 
00686         {
00687                 return qfalse;
00688         }
00689                 
00690         // parse the saber info block
00691         while ( 1 ) 
00692         {
00693                 token = COM_ParseExt( &p, qtrue );
00694                 if ( !token[0] ) 
00695                 {
00696                         Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", useSaber );
00697                         return qfalse;
00698                 }
00699 
00700                 if ( !Q_stricmp( token, "}" ) ) 
00701                 {
00702                         break;
00703                 }
00704 
00705                 //saber fullName
00706                 if ( !Q_stricmp( token, "name" ) ) 
00707                 {
00708                         if ( COM_ParseString( &p, &value ) ) 
00709                         {
00710                                 continue;
00711                         }
00712                         strcpy(saber->fullName, value);
00713                         continue;
00714                 }
00715 
00716                 //saber type
00717                 if ( !Q_stricmp( token, "saberType" ) ) 
00718                 {
00719                         int saberType;
00720 
00721                         if ( COM_ParseString( &p, &value ) ) 
00722                         {
00723                                 continue;
00724                         }
00725                         saberType = GetIDForString( SaberTable, value );
00726                         if ( saberType >= SABER_SINGLE && saberType <= NUM_SABERS )
00727                         {
00728                                 saber->type = (saberType_t)saberType;
00729                         }
00730                         continue;
00731                 }
00732 
00733                 //saber hilt
00734                 if ( !Q_stricmp( token, "saberModel" ) ) 
00735                 {
00736                         if ( COM_ParseString( &p, &value ) ) 
00737                         {
00738                                 continue;
00739                         }
00740                         strcpy(saber->model, value);
00741                         continue;
00742                 }
00743 
00744                 if ( !Q_stricmp( token, "customSkin" ) )
00745                 {
00746                         if ( COM_ParseString( &p, &value ) ) 
00747                         {
00748                                 continue;
00749                         }
00750                         saber->skin = trap_R_RegisterSkin(value);
00751                         continue;
00752                 }
00753 
00754                 //on sound
00755                 if ( !Q_stricmp( token, "soundOn" ) ) 
00756                 {
00757                         if ( COM_ParseString( &p, &value ) ) 
00758                         {
00759                                 continue;
00760                         }
00761                         saber->soundOn = BG_SoundIndex( (char *)value );
00762                         continue;
00763                 }
00764 
00765                 //loop sound
00766                 if ( !Q_stricmp( token, "soundLoop" ) ) 
00767                 {
00768                         if ( COM_ParseString( &p, &value ) ) 
00769                         {
00770                                 continue;
00771                         }
00772                         saber->soundLoop = BG_SoundIndex( (char *)value );
00773                         continue;
00774                 }
00775 
00776                 //off sound
00777                 if ( !Q_stricmp( token, "soundOff" ) ) 
00778                 {
00779                         if ( COM_ParseString( &p, &value ) ) 
00780                         {
00781                                 continue;
00782                         }
00783                         saber->soundOff = BG_SoundIndex( (char *)value );
00784                         continue;
00785                 }
00786 
00787                 if ( !Q_stricmp( token, "numBlades" ) ) 
00788                 {
00789                         if ( COM_ParseInt( &p, &n ) ) 
00790                         {
00791                                 SkipRestOfLine( &p );
00792                                 continue;
00793                         }
00794                         if ( n < 1 || n > MAX_BLADES )
00795                         {
00796                                 Com_Error(ERR_DROP, "WP_SaberParseParms: saber %s has illegal number of blades (%d) max: %d", useSaber, n, MAX_BLADES );
00797                                 continue;
00798                         }
00799                         saber->numBlades = n;
00800                         continue;
00801                 }
00802 
00803                 // saberColor
00804                 if ( !Q_stricmpn( token, "saberColor", 10 ) ) 
00805                 {
00806                         if (strlen(token)==10)
00807                         {
00808                                 n = -1;
00809                         }
00810                         else if (strlen(token)==11)
00811                         {
00812                                 n = atoi(&token[10])-1;
00813                                 if (n > 7 || n < 1 )
00814                                 {
00815                                         Com_Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, useSaber );
00816                                         continue;
00817                                 }
00818                         }
00819                         else
00820                         {
00821                                 Com_Printf( S_COLOR_YELLOW"WARNING: bad saberColor '%s' in %s\n", token, useSaber );
00822                                 continue;
00823                         }
00824 
00825                         if ( COM_ParseString( &p, &value ) )    //read the color
00826                         {
00827                                 continue;
00828                         }
00829 
00830                         if (n==-1)
00831                         {//NOTE: this fills in the rest of the blades with the same color by default
00832                                 saber_colors_t color = TranslateSaberColor( value );
00833                                 for ( n = 0; n < MAX_BLADES; n++ )
00834                                 {
00835                                         saber->blade[n].color = color;
00836                                 }
00837                         } else 
00838                         {
00839                                 saber->blade[n].color = TranslateSaberColor( value );
00840                         }
00841                         continue;
00842                 }
00843 
00844                 //saber length
00845                 if ( !Q_stricmpn( token, "saberLength", 11 ) ) 
00846                 {
00847                         if (strlen(token)==11)
00848                         {
00849                                 n = -1;
00850                         }
00851                         else if (strlen(token)==12)
00852                         {
00853                                 n = atoi(&token[11])-1;
00854                                 if (n > 7 || n < 1 )
00855                                 {
00856                                         Com_Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, useSaber );
00857                                         continue;
00858                                 }
00859                         }
00860                         else
00861                         {
00862                                 Com_Printf( S_COLOR_YELLOW"WARNING: bad saberLength '%s' in %s\n", token, useSaber );
00863                                 continue;
00864                         }
00865 
00866                         if ( COM_ParseFloat( &p, &f ) ) 
00867                         {
00868                                 SkipRestOfLine( &p );
00869                                 continue;
00870                         }
00871                         //cap
00872                         if ( f < 4.0f )
00873                         {
00874                                 f = 4.0f;
00875                         }
00876 
00877                         if (n==-1)
00878                         {//NOTE: this fills in the rest of the blades with the same length by default
00879                                 for ( n = 0; n < MAX_BLADES; n++ )
00880                                 {
00881                                         saber->blade[n].lengthMax = f;
00882                                 }
00883                         }
00884                         else
00885                         {
00886                                 saber->blade[n].lengthMax = f;
00887                         }
00888                         continue;
00889                 }
00890 
00891                 //blade radius
00892                 if ( !Q_stricmpn( token, "saberRadius", 11 ) ) 
00893                 {
00894                         if (strlen(token)==11)
00895                         {
00896                                 n = -1;
00897                         }
00898                         else if (strlen(token)==12)
00899                         {
00900                                 n = atoi(&token[11])-1;
00901                                 if (n > 7 || n < 1 )
00902                                 {
00903                                         Com_Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, useSaber );
00904                                         continue;
00905                                 }
00906                         }
00907                         else
00908                         {
00909                                 Com_Printf( S_COLOR_YELLOW"WARNING: bad saberRadius '%s' in %s\n", token, useSaber );
00910                                 continue;
00911                         }
00912 
00913                         if ( COM_ParseFloat( &p, &f ) ) 
00914                         {
00915                                 SkipRestOfLine( &p );
00916                                 continue;
00917                         }
00918                         //cap
00919                         if ( f < 0.25f )
00920                         {
00921                                 f = 0.25f;
00922                         }
00923                         if (n==-1)
00924                         {//NOTE: this fills in the rest of the blades with the same length by default
00925                                 for ( n = 0; n < MAX_BLADES; n++ )
00926                                 {
00927                                         saber->blade[n].radius = f;
00928                                 }
00929                         }
00930                         else
00931                         {
00932                                 saber->blade[n].radius = f;
00933                         }
00934                         continue;
00935                 }
00936 
00937                 //locked saber style
00938                 if ( !Q_stricmp( token, "saberStyle" ) ) 
00939                 {
00940                         int style, styleNum;
00941                         if ( COM_ParseString( &p, &value ) ) 
00942                         {
00943                                 continue;
00944                         }
00945                         //OLD WAY: only allowed ONE style
00946                         style = TranslateSaberStyle( value );
00947                         //learn only this style
00948                         saber->stylesLearned = (1<<style);
00949                         //forbid all other styles
00950                         saber->stylesForbidden = 0;
00951                         for ( styleNum = SS_NONE+1; styleNum < SS_NUM_SABER_STYLES; styleNum++ )
00952                         {
00953                                 if ( styleNum != style )
00954                                 {
00955                                         saber->stylesForbidden |= (1<<styleNum);
00956                                 }
00957                         }
00958                         continue;
00959                 }
00960 
00961                 //learned saber style
00962                 if ( !Q_stricmp( token, "saberStyleLearned" ) ) 
00963                 {
00964                         if ( COM_ParseString( &p, &value ) ) 
00965                         {
00966                                 continue;
00967                         }
00968                         saber->stylesLearned |= (1<<TranslateSaberStyle( value ));
00969                         continue;
00970                 }
00971 
00972                 //forbidden saber style
00973                 if ( !Q_stricmp( token, "saberStyleForbidden" ) ) 
00974                 {
00975                         if ( COM_ParseString( &p, &value ) ) 
00976                         {
00977                                 continue;
00978                         }
00979                         saber->stylesForbidden |= (1<<TranslateSaberStyle( value ));
00980                         continue;
00981                 }
00982 
00983                 //maxChain
00984                 if ( !Q_stricmp( token, "maxChain" ) ) 
00985                 {
00986                         if ( COM_ParseInt( &p, &n ) ) 
00987                         {
00988                                 SkipRestOfLine( &p );
00989                                 continue;
00990                         }
00991                         saber->maxChain = n;
00992                         continue;
00993                 }
00994 
00995                 //lockable
00996                 if ( !Q_stricmp( token, "lockable" ) ) 
00997                 {
00998                         if ( COM_ParseInt( &p, &n ) ) 
00999                         {
01000                                 SkipRestOfLine( &p );
01001                                 continue;
01002                         }
01003                         if ( n == 0 )
01004                         {
01005                                 saber->saberFlags |= SFL_NOT_LOCKABLE;
01006                         }
01007                         continue;
01008                 }
01009 
01010                 //throwable
01011                 if ( !Q_stricmp( token, "throwable" ) ) 
01012                 {
01013                         if ( COM_ParseInt( &p, &n ) ) 
01014                         {
01015                                 SkipRestOfLine( &p );
01016                                 continue;
01017                         }
01018                         if ( n == 0 )
01019                         {
01020                                 saber->saberFlags |= SFL_NOT_THROWABLE;
01021                         }
01022                         continue;
01023                 }
01024 
01025                 //disarmable
01026                 if ( !Q_stricmp( token, "disarmable" ) ) 
01027                 {
01028                         if ( COM_ParseInt( &p, &n ) ) 
01029                         {
01030                                 SkipRestOfLine( &p );
01031                                 continue;
01032                         }
01033                         if ( n == 0 )
01034                         {
01035                                 saber->saberFlags |= SFL_NOT_DISARMABLE;
01036                         }
01037                         continue;
01038                 }
01039 
01040                 //active blocking
01041                 if ( !Q_stricmp( token, "blocking" ) ) 
01042                 {
01043                         if ( COM_ParseInt( &p, &n ) ) 
01044                         {
01045                                 SkipRestOfLine( &p );
01046                                 continue;
01047                         }
01048                         if ( n == 0 )
01049                         {
01050                                 saber->saberFlags |= SFL_NOT_ACTIVE_BLOCKING;
01051                         }
01052                         continue;
01053                 }
01054 
01055                 //twoHanded
01056                 if ( !Q_stricmp( token, "twoHanded" ) ) 
01057                 {
01058                         if ( COM_ParseInt( &p, &n ) ) 
01059                         {
01060                                 SkipRestOfLine( &p );
01061                                 continue;
01062                         }
01063                         if ( n )
01064                         {
01065                                 saber->saberFlags |= SFL_TWO_HANDED;
01066                         }
01067                         continue;
01068                 }
01069 
01070                 //force power restrictions
01071                 if ( !Q_stricmp( token, "forceRestrict" ) ) 
01072                 {
01073                         int fp;
01074 
01075                         if ( COM_ParseString( &p, &value ) ) 
01076                         {
01077                                 continue;
01078                         }
01079                         fp = GetIDForString( FPTable, value );
01080                         if ( fp >= FP_FIRST && fp < NUM_FORCE_POWERS )
01081                         {
01082                                 saber->forceRestrictions |= (1<<fp);
01083                         }
01084                         continue;
01085                 }
01086 
01087                 //lockBonus
01088                 if ( !Q_stricmp( token, "lockBonus" ) ) 
01089                 {
01090                         if ( COM_ParseInt( &p, &n ) ) 
01091                         {
01092                                 SkipRestOfLine( &p );
01093                                 continue;
01094                         }
01095                         saber->lockBonus = n;
01096                         continue;
01097                 }
01098 
01099                 //parryBonus
01100                 if ( !Q_stricmp( token, "parryBonus" ) ) 
01101                 {
01102                         if ( COM_ParseInt( &p, &n ) ) 
01103                         {
01104                                 SkipRestOfLine( &p );
01105                                 continue;
01106                         }
01107                         saber->parryBonus = n;
01108                         continue;
01109                 }
01110 
01111                 //breakParryBonus
01112                 if ( !Q_stricmp( token, "breakParryBonus" ) ) 
01113                 {
01114                         if ( COM_ParseInt( &p, &n ) ) 
01115                         {
01116                                 SkipRestOfLine( &p );
01117                                 continue;
01118                         }
01119                         saber->breakParryBonus = n;
01120                         continue;
01121                 }
01122 
01123                 //breakParryBonus2
01124                 if ( !Q_stricmp( token, "breakParryBonus2" ) ) 
01125                 {
01126                         if ( COM_ParseInt( &p, &n ) ) 
01127                         {
01128                                 SkipRestOfLine( &p );
01129                                 continue;
01130                         }
01131                         saber->breakParryBonus2 = n;
01132                         continue;
01133                 }
01134 
01135                 //disarmBonus
01136                 if ( !Q_stricmp( token, "disarmBonus" ) ) 
01137                 {
01138                         if ( COM_ParseInt( &p, &n ) ) 
01139                         {
01140                                 SkipRestOfLine( &p );
01141                                 continue;
01142                         }
01143                         saber->disarmBonus = n;
01144                         continue;
01145                 }
01146 
01147                 //disarmBonus2
01148                 if ( !Q_stricmp( token, "disarmBonus2" ) ) 
01149                 {
01150                         if ( COM_ParseInt( &p, &n ) ) 
01151                         {
01152                                 SkipRestOfLine( &p );
01153                                 continue;
01154                         }
01155                         saber->disarmBonus2 = n;
01156                         continue;
01157                 }
01158 
01159                 //single blade saber style
01160                 if ( !Q_stricmp( token, "singleBladeStyle" ) ) 
01161                 {
01162                         if ( COM_ParseString( &p, &value ) ) 
01163                         {
01164                                 continue;
01165                         }
01166                         saber->singleBladeStyle = TranslateSaberStyle( value );
01167                         continue;
01168                 }
01169 
01170                 //single blade throwable
01171                 if ( !Q_stricmp( token, "singleBladeThrowable" ) ) 
01172                 {
01173                         if ( COM_ParseInt( &p, &n ) ) 
01174                         {
01175                                 SkipRestOfLine( &p );
01176                                 continue;
01177                         }
01178                         if ( n )
01179                         {
01180                                 saber->saberFlags |= SFL_SINGLE_BLADE_THROWABLE;
01181                         }
01182                         continue;
01183                 }
01184 
01185                 //broken replacement saber1 (right hand)
01186                 if ( !Q_stricmp( token, "brokenSaber1" ) ) 
01187                 {
01188                         if ( COM_ParseString( &p, &value ) ) 
01189                         {
01190                                 continue;
01191                         }
01192                         //saber->brokenSaber1 = G_NewString( value );
01193                         continue;
01194                 }
01195                 
01196                 //broken replacement saber2 (left hand)
01197                 if ( !Q_stricmp( token, "brokenSaber2" ) ) 
01198                 {
01199                         if ( COM_ParseString( &p, &value ) ) 
01200                         {
01201                                 continue;
01202                         }
01203                         //saber->brokenSaber2 = G_NewString( value );
01204                         continue;
01205                 }
01206 
01207                 //spins and does damage on return from saberthrow
01208                 if ( !Q_stricmp( token, "returnDamage" ) ) 
01209                 {
01210                         if ( COM_ParseInt( &p, &n ) ) 
01211                         {
01212                                 SkipRestOfLine( &p );
01213                                 continue;
01214                         }
01215                         if ( n )
01216                         {
01217                                 saber->saberFlags |= SFL_RETURN_DAMAGE;
01218                         }
01219                         continue;
01220                 }
01221 
01222                 //spin sound (when thrown)
01223                 if ( !Q_stricmp( token, "spinSound" ) ) 
01224                 {
01225                         if ( COM_ParseString( &p, &value ) ) 
01226                         {
01227                                 continue;
01228                         }
01229                         saber->spinSound = BG_SoundIndex( (char *)value );
01230                         continue;
01231                 }
01232 
01233                 //swing sound - NOTE: must provide all 3!!!
01234                 if ( !Q_stricmp( token, "swingSound1" ) ) 
01235                 {
01236                         if ( COM_ParseString( &p, &value ) ) 
01237                         {
01238                                 continue;
01239                         }
01240                         saber->swingSound[0] = BG_SoundIndex( (char *)value );
01241                         continue;
01242                 }
01243 
01244                 //swing sound - NOTE: must provide all 3!!!
01245                 if ( !Q_stricmp( token, "swingSound2" ) ) 
01246                 {
01247                         if ( COM_ParseString( &p, &value ) ) 
01248                         {
01249                                 continue;
01250                         }
01251                         saber->swingSound[1] = BG_SoundIndex( (char *)value );
01252                         continue;
01253                 }
01254 
01255                 //swing sound - NOTE: must provide all 3!!!
01256                 if ( !Q_stricmp( token, "swingSound3" ) ) 
01257                 {
01258                         if ( COM_ParseString( &p, &value ) ) 
01259                         {
01260                                 continue;
01261                         }
01262                         saber->swingSound[2] = BG_SoundIndex( (char *)value );
01263                         continue;
01264                 }
01265 
01266                 //you move faster/slower when using this saber
01267                 if ( !Q_stricmp( token, "moveSpeedScale" ) ) 
01268                 {
01269                         if ( COM_ParseFloat( &p, &f ) ) 
01270                         {
01271                                 SkipRestOfLine( &p );
01272                                 continue;
01273                         }
01274                         saber->moveSpeedScale = f;
01275                         continue;
01276                 }
01277 
01278                 //plays normal attack animations faster/slower
01279                 if ( !Q_stricmp( token, "animSpeedScale" ) ) 
01280                 {
01281                         if ( COM_ParseFloat( &p, &f ) ) 
01282                         {
01283                                 SkipRestOfLine( &p );
01284                                 continue;
01285                         }
01286                         saber->animSpeedScale = f;
01287                         continue;
01288                 }
01289 
01290                 //if non-zero, the saber will bounce back when it hits solid architecture (good for real-sword type mods)
01291                 if ( !Q_stricmp( token, "bounceOnWalls" ) ) 
01292                 {
01293                         if ( COM_ParseInt( &p, &n ) ) 
01294                         {
01295                                 SkipRestOfLine( &p );
01296                                 continue;
01297                         }
01298                         if ( n )
01299                         {
01300                                 saber->saberFlags |= SFL_BOUNCE_ON_WALLS;
01301                         }
01302                         continue;
01303                 }
01304 
01305                 //if set, saber model is bolted to wrist, not in hand... useful for things like claws & shields, etc.
01306                 if ( !Q_stricmp( token, "boltToWrist" ) ) 
01307                 {
01308                         if ( COM_ParseInt( &p, &n ) ) 
01309                         {
01310                                 SkipRestOfLine( &p );
01311                                 continue;
01312                         }
01313                         if ( n )
01314                         {
01315                                 saber->saberFlags |= SFL_BOLT_TO_WRIST;
01316                         }
01317                         continue;
01318                 }
01319 
01320                 //kata move
01321                 if ( !Q_stricmp( token, "kataMove" ) ) 
01322                 {
01323                         if ( COM_ParseString( &p, &value ) ) 
01324                         {
01325                                 continue;
01326                         }
01327                         saberMove = GetIDForString( SaberMoveTable, value );
01328                         if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
01329                         {
01330                                 saber->kataMove = saberMove;                            //LS_INVALID - if set, player will execute this move when they press both attack buttons at the same time 
01331                         }
01332                         continue;
01333                 }
01334                 //lungeAtkMove move
01335                 if ( !Q_stricmp( token, "lungeAtkMove" ) ) 
01336                 {
01337                         if ( COM_ParseString( &p, &value ) ) 
01338                         {
01339                                 continue;
01340                         }
01341                         saberMove = GetIDForString( SaberMoveTable, value );
01342                         if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
01343                         {
01344                                 saber->lungeAtkMove = saberMove;
01345                         }
01346                         continue;
01347                 }
01348                 //jumpAtkUpMove move
01349                 if ( !Q_stricmp( token, "jumpAtkUpMove" ) ) 
01350                 {
01351                         if ( COM_ParseString( &p, &value ) ) 
01352                         {
01353                                 continue;
01354                         }
01355                         saberMove = GetIDForString( SaberMoveTable, value );
01356                         if ( saberMove >= LS_INVALID && saberMove < LS_MOVE_MAX )
01357                         {
01358                                 saber->jumpAtkUpMove = saberMove;
01359                         }
01360                         continue;
01361                 }
01362                 //jumpAtkFwdMove move
01363