00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ui_local.h"
00014 #include "ui_shared.h"
00015
00016
00017 #define MAX_SABER_DATA_SIZE 0x80000
00018
00019
00020
00021
00022 static char SaberParms[MAX_SABER_DATA_SIZE];
00023 qboolean ui_saber_parms_parsed = qfalse;
00024
00025 static qhandle_t redSaberGlowShader;
00026 static qhandle_t redSaberCoreShader;
00027 static qhandle_t orangeSaberGlowShader;
00028 static qhandle_t orangeSaberCoreShader;
00029 static qhandle_t yellowSaberGlowShader;
00030 static qhandle_t yellowSaberCoreShader;
00031 static qhandle_t greenSaberGlowShader;
00032 static qhandle_t greenSaberCoreShader;
00033 static qhandle_t blueSaberGlowShader;
00034 static qhandle_t blueSaberCoreShader;
00035 static qhandle_t purpleSaberGlowShader;
00036 static qhandle_t purpleSaberCoreShader;
00037
00038 void UI_CacheSaberGlowGraphics( void )
00039 {
00040 redSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/red_glow" );
00041 redSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/red_line" );
00042 orangeSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/orange_glow" );
00043 orangeSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/orange_line" );
00044 yellowSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/yellow_glow" );
00045 yellowSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/yellow_line" );
00046 greenSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/green_glow" );
00047 greenSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/green_line" );
00048 blueSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/blue_glow" );
00049 blueSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/blue_line" );
00050 purpleSaberGlowShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/purple_glow" );
00051 purpleSaberCoreShader = trap_R_RegisterShaderNoMip( "gfx/effects/sabers/purple_line" );
00052 }
00053
00054 qboolean UI_ParseLiteral( const char **data, const char *string )
00055 {
00056 const char *token;
00057
00058 token = COM_ParseExt( data, qtrue );
00059 if ( token[0] == 0 )
00060 {
00061 Com_Printf( "unexpected EOF\n" );
00062 return qtrue;
00063 }
00064
00065 if ( Q_stricmp( token, string ) )
00066 {
00067 Com_Printf( "required string '%s' missing\n", string );
00068 return qtrue;
00069 }
00070
00071 return qfalse;
00072 }
00073
00074 qboolean UI_ParseLiteralSilent( const char **data, const char *string )
00075 {
00076 const char *token;
00077
00078 token = COM_ParseExt( data, qtrue );
00079 if ( token[0] == 0 )
00080 {
00081 return qtrue;
00082 }
00083
00084 if ( Q_stricmp( token, string ) )
00085 {
00086 return qtrue;
00087 }
00088
00089 return qfalse;
00090 }
00091
00092 qboolean UI_SaberParseParm( const char *saberName, const char *parmname, char *saberData )
00093 {
00094 const char *token;
00095 const char *value;
00096 const char *p;
00097
00098 if ( !saberName || !saberName[0] )
00099 {
00100 return qfalse;
00101 }
00102
00103
00104 p = SaberParms;
00105
00106 COM_BeginParseSession("saberinfo");
00107
00108
00109 while ( p )
00110 {
00111 token = COM_ParseExt( &p, qtrue );
00112 if ( token[0] == 0 )
00113 {
00114 return qfalse;
00115 }
00116
00117 if ( !Q_stricmp( token, saberName ) )
00118 {
00119 break;
00120 }
00121
00122 SkipBracedSection( &p );
00123 }
00124 if ( !p )
00125 {
00126 return qfalse;
00127 }
00128
00129 if ( UI_ParseLiteral( &p, "{" ) )
00130 {
00131 return qfalse;
00132 }
00133
00134
00135 while ( 1 )
00136 {
00137 token = COM_ParseExt( &p, qtrue );
00138 if ( !token[0] )
00139 {
00140 Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", saberName );
00141 return qfalse;
00142 }
00143
00144 if ( !Q_stricmp( token, "}" ) )
00145 {
00146 break;
00147 }
00148
00149 if ( !Q_stricmp( token, parmname ) )
00150 {
00151 if ( COM_ParseString( &p, &value ) )
00152 {
00153 continue;
00154 }
00155 strcpy( saberData, value );
00156 return qtrue;
00157 }
00158
00159 SkipRestOfLine( &p );
00160 continue;
00161 }
00162
00163 return qfalse;
00164 }
00165
00166
00167 qboolean UI_SaberModelForSaber( const char *saberName, char *saberModel )
00168 {
00169 return UI_SaberParseParm( saberName, "saberModel", saberModel );
00170 }
00171
00172 qboolean UI_SaberSkinForSaber( const char *saberName, char *saberSkin )
00173 {
00174 return UI_SaberParseParm( saberName, "customSkin", saberSkin );
00175 }
00176
00177 qboolean UI_SaberTypeForSaber( const char *saberName, char *saberType )
00178 {
00179 return UI_SaberParseParm( saberName, "saberType", saberType );
00180 }
00181
00182 int UI_SaberNumBladesForSaber( const char *saberName )
00183 {
00184 int numBlades;
00185 char numBladesString[8]={0};
00186 UI_SaberParseParm( saberName, "numBlades", numBladesString );
00187 numBlades = atoi( numBladesString );
00188 if ( numBlades < 1 )
00189 {
00190 numBlades = 1;
00191 }
00192 else if ( numBlades > 8 )
00193 {
00194 numBlades = 8;
00195 }
00196 return numBlades;
00197 }
00198
00199 qboolean UI_SaberShouldDrawBlade( const char *saberName, int bladeNum )
00200 {
00201 int bladeStyle2Start = 0, noBlade = 0;
00202 char bladeStyle2StartString[8]={0};
00203 char noBladeString[8]={0};
00204 UI_SaberParseParm( saberName, "bladeStyle2Start", bladeStyle2StartString );
00205 if ( bladeStyle2StartString
00206 && bladeStyle2StartString[0] )
00207 {
00208 bladeStyle2Start = atoi( bladeStyle2StartString );
00209 }
00210 if ( bladeStyle2Start
00211 && bladeNum >= bladeStyle2Start )
00212 {
00213 UI_SaberParseParm( saberName, "noBlade2", noBladeString );
00214 if ( noBladeString
00215 && noBladeString[0] )
00216 {
00217 noBlade = atoi( noBladeString );
00218 }
00219 }
00220 else
00221 {
00222 UI_SaberParseParm( saberName, "noBlade", noBladeString );
00223 if ( noBladeString
00224 && noBladeString[0] )
00225 {
00226 noBlade = atoi( noBladeString );
00227 }
00228 }
00229 return ((qboolean)(noBlade==0));
00230 }
00231
00232
00233 qboolean UI_IsSaberTwoHanded( const char *saberName )
00234 {
00235 int twoHanded;
00236 char twoHandedString[8]={0};
00237 UI_SaberParseParm( saberName, "twoHanded", twoHandedString );
00238 if ( !twoHandedString[0] )
00239 {
00240 return qfalse;
00241 }
00242 twoHanded = atoi( twoHandedString );
00243 return ((qboolean)(twoHanded!=0));
00244 }
00245
00246 float UI_SaberBladeLengthForSaber( const char *saberName, int bladeNum )
00247 {
00248 char lengthString[8]={0};
00249 float length = 40.0f;
00250 UI_SaberParseParm( saberName, "saberLength", lengthString );
00251 if ( lengthString[0] )
00252 {
00253 length = atof( lengthString );
00254 if ( length < 0.0f )
00255 {
00256 length = 0.0f;
00257 }
00258 }
00259
00260 UI_SaberParseParm( saberName, va("saberLength%d", bladeNum+1), lengthString );
00261 if ( lengthString[0] )
00262 {
00263 length = atof( lengthString );
00264 if ( length < 0.0f )
00265 {
00266 length = 0.0f;
00267 }
00268 }
00269
00270 return length;
00271 }
00272
00273 float UI_SaberBladeRadiusForSaber( const char *saberName, int bladeNum )
00274 {
00275 char radiusString[8]={0};
00276 float radius = 3.0f;
00277 UI_SaberParseParm( saberName, "saberRadius", radiusString );
00278 if ( radiusString[0] )
00279 {
00280 radius = atof( radiusString );
00281 if ( radius < 0.0f )
00282 {
00283 radius = 0.0f;
00284 }
00285 }
00286
00287 UI_SaberParseParm( saberName, va("saberRadius%d", bladeNum+1), radiusString );
00288 if ( radiusString[0] )
00289 {
00290 radius = atof( radiusString );
00291 if ( radius < 0.0f )
00292 {
00293 radius = 0.0f;
00294 }
00295 }
00296
00297 return radius;
00298 }
00299
00300 qboolean UI_SaberProperNameForSaber( const char *saberName, char *saberProperName )
00301 {
00302 char stringedSaberName[1024];
00303 qboolean ret = UI_SaberParseParm( saberName, "name", stringedSaberName );
00304
00305 if( ret && stringedSaberName && stringedSaberName[0] == '@')
00306 {
00307 trap_SP_GetStringTextString(&stringedSaberName[1], saberProperName, 1024);
00308 }
00309 else
00310 {
00311
00312 strcpy( saberProperName, stringedSaberName );
00313 }
00314
00315 return ret;
00316
00317 }
00318
00319 qboolean UI_SaberValidForPlayerInMP( const char *saberName )
00320 {
00321 char allowed [8]={0};
00322 if ( !UI_SaberParseParm( saberName, "notInMP", allowed ) )
00323 {
00324 return qtrue;
00325 }
00326 if ( !allowed[0] )
00327 {
00328 return qtrue;
00329 }
00330 else
00331 {
00332 return ((qboolean)(atoi(allowed)==0));
00333 }
00334 }
00335
00336 void UI_SaberLoadParms( void )
00337 {
00338 int len, totallen, saberExtFNLen, fileCnt, i;
00339 char *holdChar, *marker;
00340 char saberExtensionListBuf[2048];
00341 fileHandle_t f;
00342 char buffer[MAX_MENUFILE];
00343
00344
00345
00346 ui_saber_parms_parsed = qtrue;
00347 UI_CacheSaberGlowGraphics();
00348
00349
00350 totallen = 0;
00351 marker = SaberParms;
00352 marker[0] = '\0';
00353
00354
00355 fileCnt = trap_FS_GetFileList("ext_data/sabers", ".sab", saberExtensionListBuf, sizeof(saberExtensionListBuf) );
00356
00357 holdChar = saberExtensionListBuf;
00358 for ( i = 0; i < fileCnt; i++, holdChar += saberExtFNLen + 1 )
00359 {
00360 saberExtFNLen = strlen( holdChar );
00361
00362 len = trap_FS_FOpenFile( va( "ext_data/sabers/%s", holdChar), &f, FS_READ );
00363
00364 if (!f)
00365 {
00366 continue;
00367 }
00368
00369 if ( len == -1 )
00370 {
00371 Com_Printf( "UI_SaberLoadParms: error reading %s\n", holdChar );
00372 }
00373 else
00374 {
00375 if (len > sizeof(buffer) )
00376 {
00377 Com_Error( ERR_FATAL, "UI_SaberLoadParms: file %s too large to read (max=%d)", holdChar, sizeof(buffer) );
00378 }
00379 trap_FS_Read( buffer, len, f );
00380 trap_FS_FCloseFile( f );
00381 buffer[len] = 0;
00382
00383 if ( totallen && *(marker-1) == '}' )
00384 {
00385 strcat( marker, " " );
00386 totallen++;
00387 marker++;
00388 }
00389 len = COM_Compress( buffer );
00390
00391 if ( totallen + len >= MAX_SABER_DATA_SIZE ) {
00392 Com_Error( ERR_FATAL, "UI_SaberLoadParms: ran out of space before reading %s\n(you must make the .sab files smaller)", holdChar );
00393 }
00394 strcat( marker, buffer );
00395
00396 totallen += len;
00397 marker += len;
00398 }
00399 }
00400 }
00401
00402 void UI_DoSaber( vec3_t origin, vec3_t dir, float length, float lengthMax, float radius, saber_colors_t color )
00403 {
00404 vec3_t mid, rgb={1,1,1};
00405 qhandle_t blade = 0, glow = 0;
00406 refEntity_t saber;
00407 float radiusmult;
00408 float radiusRange;
00409 float radiusStart;
00410
00411 if ( length < 0.5f )
00412 {
00413
00414 return;
00415 }
00416
00417
00418 VectorMA( origin, length * 0.5f, dir, mid );
00419
00420 switch( color )
00421 {
00422 case SABER_RED:
00423 glow = redSaberGlowShader;
00424 blade = redSaberCoreShader;
00425 VectorSet( rgb, 1.0f, 0.2f, 0.2f );
00426 break;
00427 case SABER_ORANGE:
00428 glow = orangeSaberGlowShader;
00429 blade = orangeSaberCoreShader;
00430 VectorSet( rgb, 1.0f, 0.5f, 0.1f );
00431 break;
00432 case SABER_YELLOW:
00433 glow = yellowSaberGlowShader;
00434 blade = yellowSaberCoreShader;
00435 VectorSet( rgb, 1.0f, 1.0f, 0.2f );
00436 break;
00437 case SABER_GREEN:
00438 glow = greenSaberGlowShader;
00439 blade = greenSaberCoreShader;
00440 VectorSet( rgb, 0.2f, 1.0f, 0.2f );
00441 break;
00442 case SABER_BLUE:
00443 glow = blueSaberGlowShader;
00444 blade = blueSaberCoreShader;
00445 VectorSet( rgb, 0.2f, 0.4f, 1.0f );
00446 break;
00447 case SABER_PURPLE:
00448 glow = purpleSaberGlowShader;
00449 blade = purpleSaberCoreShader;
00450 VectorSet( rgb, 0.9f, 0.2f, 1.0f );
00451 break;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 memset( &saber, 0, sizeof( refEntity_t ));
00463
00464
00465
00466 saber.saberLength = length;
00467
00468
00469
00470 if (length < lengthMax )
00471 {
00472 radiusmult = 1.0 + (2.0 / length);
00473 }
00474 else
00475 {
00476 radiusmult = 1.0;
00477 }
00478
00479 radiusRange = radius * 0.075f;
00480 radiusStart = radius-radiusRange;
00481
00482 saber.radius = (radiusStart + crandom() * radiusRange)*radiusmult;
00483
00484
00485
00486 VectorCopy( origin, saber.origin );
00487 VectorCopy( dir, saber.axis[0] );
00488 saber.reType = RT_SABER_GLOW;
00489 saber.customShader = glow;
00490 saber.shaderRGBA[0] = saber.shaderRGBA[1] = saber.shaderRGBA[2] = saber.shaderRGBA[3] = 0xff;
00491
00492
00493 trap_R_AddRefEntityToScene( &saber );
00494
00495
00496 VectorMA( origin, length, dir, saber.origin );
00497 VectorMA( origin, -1, dir, saber.oldorigin );
00498 saber.customShader = blade;
00499 saber.reType = RT_LINE;
00500 radiusStart = radius/3.0f;
00501 saber.radius = (radiusStart + crandom() * radiusRange)*radiusmult;
00502
00503
00504 trap_R_AddRefEntityToScene( &saber );
00505 }
00506
00507 char * SaberColorToString(saber_colors_t color)
00508 {
00509 if ( color == SABER_RED)
00510 return "red";
00511
00512 if ( color == SABER_ORANGE)
00513 return "orange";
00514
00515 if ( color == SABER_YELLOW)
00516 return "yellow";
00517
00518 if ( color == SABER_GREEN)
00519 return "green";
00520
00521 if (color == SABER_BLUE)
00522 return "blue";
00523
00524 if ( color == SABER_PURPLE)
00525 return "purple";
00526 return NULL;
00527 }
00528 saber_colors_t TranslateSaberColor( const char *name )
00529 {
00530 if ( !Q_stricmp( name, "red" ) )
00531 {
00532 return SABER_RED;
00533 }
00534 if ( !Q_stricmp( name, "orange" ) )
00535 {
00536 return SABER_ORANGE;
00537 }
00538 if ( !Q_stricmp( name, "yellow" ) )
00539 {
00540 return SABER_YELLOW;
00541 }
00542 if ( !Q_stricmp( name, "green" ) )
00543 {
00544 return SABER_GREEN;
00545 }
00546 if ( !Q_stricmp( name, "blue" ) )
00547 {
00548 return SABER_BLUE;
00549 }
00550 if ( !Q_stricmp( name, "purple" ) )
00551 {
00552 return SABER_PURPLE;
00553 }
00554 if ( !Q_stricmp( name, "random" ) )
00555 {
00556 return ((saber_colors_t)(Q_irand( SABER_ORANGE, SABER_PURPLE )));
00557 }
00558 return SABER_BLUE;
00559 }
00560
00561 saberType_t TranslateSaberType( const char *name )
00562 {
00563 if ( !Q_stricmp( name, "SABER_SINGLE" ) )
00564 {
00565 return SABER_SINGLE;
00566 }
00567 if ( !Q_stricmp( name, "SABER_STAFF" ) )
00568 {
00569 return SABER_STAFF;
00570 }
00571 if ( !Q_stricmp( name, "SABER_BROAD" ) )
00572 {
00573 return SABER_BROAD;
00574 }
00575 if ( !Q_stricmp( name, "SABER_PRONG" ) )
00576 {
00577 return SABER_PRONG;
00578 }
00579 if ( !Q_stricmp( name, "SABER_DAGGER" ) )
00580 {
00581 return SABER_DAGGER;
00582 }
00583 if ( !Q_stricmp( name, "SABER_ARC" ) )
00584 {
00585 return SABER_ARC;
00586 }
00587 if ( !Q_stricmp( name, "SABER_SAI" ) )
00588 {
00589 return SABER_SAI;
00590 }
00591 if ( !Q_stricmp( name, "SABER_CLAW" ) )
00592 {
00593 return SABER_CLAW;
00594 }
00595 if ( !Q_stricmp( name, "SABER_LANCE" ) )
00596 {
00597 return SABER_LANCE;
00598 }
00599 if ( !Q_stricmp( name, "SABER_STAR" ) )
00600 {
00601 return SABER_STAR;
00602 }
00603 if ( !Q_stricmp( name, "SABER_TRIDENT" ) )
00604 {
00605 return SABER_TRIDENT;
00606 }
00607 if ( !Q_stricmp( name, "SABER_SITH_SWORD" ) )
00608 {
00609 return SABER_SITH_SWORD;
00610 }
00611 return SABER_SINGLE;
00612 }
00613
00614 void UI_SaberDrawBlade( itemDef_t *item, char *saberName, int saberModel, saberType_t saberType, vec3_t origin, vec3_t angles, int bladeNum )
00615 {
00616
00617 char bladeColorString[MAX_QPATH];
00618 saber_colors_t bladeColor;
00619 float bladeLength,bladeRadius;
00620 vec3_t bladeOrigin={0};
00621 vec3_t axis[3]={0};
00622
00623 mdxaBone_t boltMatrix;
00624 qboolean tagHack = qfalse;
00625 char *tagName;
00626 int bolt;
00627 float scale;
00628
00629 if ( (item->flags&ITF_ISSABER) && saberModel < 2 )
00630 {
00631 trap_Cvar_VariableStringBuffer("ui_saber_color", bladeColorString, sizeof(bladeColorString) );
00632 }
00633 else
00634 {
00635 trap_Cvar_VariableStringBuffer("ui_saber2_color", bladeColorString, sizeof(bladeColorString) );
00636 }
00637
00638 if ( !trap_G2API_HasGhoul2ModelOnIndex(&(item->ghoul2),saberModel) )
00639 {
00640 return;
00641 }
00642
00643 bladeColor = TranslateSaberColor( bladeColorString );
00644
00645 bladeLength = UI_SaberBladeLengthForSaber( saberName, bladeNum );
00646 bladeRadius = UI_SaberBladeRadiusForSaber( saberName, bladeNum );
00647
00648 tagName = va( "*blade%d", bladeNum+1 );
00649 bolt = trap_G2API_AddBolt( item->ghoul2,saberModel, tagName );
00650
00651 if ( bolt == -1 )
00652 {
00653 tagHack = qtrue;
00654
00655 bolt = trap_G2API_AddBolt( item->ghoul2,saberModel, "*flash" );
00656 if ( bolt == -1 )
00657 {
00658 bolt = 0;
00659 }
00660 }
00661
00662
00663
00664
00665 trap_G2API_GetBoltMatrix( item->ghoul2, saberModel, bolt, &boltMatrix, angles, origin, uiInfo.uiDC.realTime, NULL, vec3_origin );
00666
00667
00668 BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, bladeOrigin);
00669 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, axis[0]);
00670
00671 BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_X, axis[1]);
00672 BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_Z, axis[2]);
00673
00674
00675
00676 scale = 1.0f;
00677
00678 if ( tagHack )
00679 {
00680 switch ( saberType )
00681 {
00682 case SABER_SINGLE:
00683 VectorMA( bladeOrigin, scale, axis[0], bladeOrigin );
00684 break;
00685 case SABER_DAGGER:
00686 case SABER_LANCE:
00687 break;
00688 case SABER_STAFF:
00689 if ( bladeNum == 0 )
00690 {
00691 VectorMA( bladeOrigin, 12*scale, axis[0], bladeOrigin );
00692 }
00693 if ( bladeNum == 1 )
00694 {
00695 VectorScale( axis[0], -1, axis[0] );
00696 VectorMA( bladeOrigin, 12*scale, axis[0], bladeOrigin );
00697 }
00698 break;
00699 case SABER_BROAD:
00700 if ( bladeNum == 0 )
00701 {
00702 VectorMA( bladeOrigin, -1*scale, axis[1], bladeOrigin );
00703 }
00704 else if ( bladeNum == 1 )
00705 {
00706 VectorMA( bladeOrigin, 1*scale, axis[1], bladeOrigin );
00707 }
00708 break;
00709 case SABER_PRONG:
00710 if ( bladeNum == 0 )
00711 {
00712 VectorMA( bladeOrigin, -3*scale, axis[1], bladeOrigin );
00713 }
00714 else if ( bladeNum == 1 )
00715 {
00716 VectorMA( bladeOrigin, 3*scale, axis[1], bladeOrigin );
00717 }
00718 break;
00719 case SABER_ARC:
00720 VectorSubtract( axis[1], axis[2], axis[1] );
00721 VectorNormalize( axis[1] );
00722 switch ( bladeNum )
00723 {
00724 case 0:
00725 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00726 VectorScale( axis[0], 0.75f, axis[0] );
00727 VectorScale( axis[1], 0.25f, axis[1] );
00728 VectorAdd( axis[0], axis[1], axis[0] );
00729 break;
00730 case 1:
00731 VectorScale( axis[0], 0.25f, axis[0] );
00732 VectorScale( axis[1], 0.75f, axis[1] );
00733 VectorAdd( axis[0], axis[1], axis[0] );
00734 break;
00735 case 2:
00736 VectorMA( bladeOrigin, -8*scale, axis[0], bladeOrigin );
00737 VectorScale( axis[0], -0.25f, axis[0] );
00738 VectorScale( axis[1], 0.75f, axis[1] );
00739 VectorAdd( axis[0], axis[1], axis[0] );
00740 break;
00741 case 3:
00742 VectorMA( bladeOrigin, -16*scale, axis[0], bladeOrigin );
00743 VectorScale( axis[0], -0.75f, axis[0] );
00744 VectorScale( axis[1], 0.25f, axis[1] );
00745 VectorAdd( axis[0], axis[1], axis[0] );
00746 break;
00747 }
00748 break;
00749 case SABER_SAI:
00750 if ( bladeNum == 1 )
00751 {
00752 VectorMA( bladeOrigin, -3*scale, axis[1], bladeOrigin );
00753 }
00754 else if ( bladeNum == 2 )
00755 {
00756 VectorMA( bladeOrigin, 3*scale, axis[1], bladeOrigin );
00757 }
00758 break;
00759 case SABER_CLAW:
00760 switch ( bladeNum )
00761 {
00762 case 0:
00763 VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin );
00764 VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin );
00765 break;
00766 case 1:
00767 VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin );
00768 VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin );
00769 VectorMA( bladeOrigin, 2*scale, axis[1], bladeOrigin );
00770 break;
00771 case 2:
00772 VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin );
00773 VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin );
00774 VectorMA( bladeOrigin, -2*scale, axis[1], bladeOrigin );
00775 break;
00776 }
00777 break;
00778 case SABER_STAR:
00779 switch ( bladeNum )
00780 {
00781 case 0:
00782 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00783 break;
00784 case 1:
00785 VectorScale( axis[0], 0.33f, axis[0] );
00786 VectorScale( axis[2], 0.67f, axis[2] );
00787 VectorAdd( axis[0], axis[2], axis[0] );
00788 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00789 break;
00790 case 2:
00791 VectorScale( axis[0], -0.33f, axis[0] );
00792 VectorScale( axis[2], 0.67f, axis[2] );
00793 VectorAdd( axis[0], axis[2], axis[0] );
00794 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00795 break;
00796 case 3:
00797 VectorScale( axis[0], -1, axis[0] );
00798 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00799 break;
00800 case 4:
00801 VectorScale( axis[0], -0.33f, axis[0] );
00802 VectorScale( axis[2], -0.67f, axis[2] );
00803 VectorAdd( axis[0], axis[2], axis[0] );
00804 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00805 break;
00806 case 5:
00807 VectorScale( axis[0], 0.33f, axis[0] );
00808 VectorScale( axis[2], -0.67f, axis[2] );
00809 VectorAdd( axis[0], axis[2], axis[0] );
00810 VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin );
00811 break;
00812 }
00813 break;
00814 case SABER_TRIDENT:
00815 switch ( bladeNum )
00816 {
00817 case 0:
00818 VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin );
00819 break;
00820 case 1:
00821 VectorMA( bladeOrigin, -6*scale, axis[1], bladeOrigin );
00822 VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin );
00823 break;
00824 case 2:
00825 VectorMA( bladeOrigin, 6*scale, axis[1], bladeOrigin );
00826 VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin );
00827 break;
00828 case 3:
00829 VectorMA( bladeOrigin, -32*scale, axis[0], bladeOrigin );
00830 VectorScale( axis[0], -1, axis[0] );
00831 break;
00832 }
00833 break;
00834 case SABER_SITH_SWORD:
00835
00836 break;
00837 }
00838 }
00839 if ( saberType == SABER_SITH_SWORD )
00840 {
00841 return;
00842 }
00843
00844 UI_DoSaber( bladeOrigin, axis[0], bladeLength, bladeLength, bladeRadius, bladeColor );
00845
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 void UI_GetSaberForMenu( char *saber, int saberNum )
00895 {
00896 char saberTypeString[MAX_QPATH]={0};
00897 saberType_t saberType = SABER_NONE;
00898
00899 if ( saberNum == 0 )
00900 {
00901 trap_Cvar_VariableStringBuffer("ui_saber", saber, MAX_QPATH );
00902 if ( !UI_SaberValidForPlayerInMP( saber ) )
00903 {
00904 trap_Cvar_Set( "ui_saber", "kyle" );
00905 trap_Cvar_VariableStringBuffer("ui_saber", saber, MAX_QPATH );
00906 }
00907 }
00908 else
00909 {
00910 trap_Cvar_VariableStringBuffer("ui_saber2", saber, MAX_QPATH );
00911 if ( !UI_SaberValidForPlayerInMP( saber ) )
00912 {
00913 trap_Cvar_Set( "ui_saber2", "kyle" );
00914 trap_Cvar_VariableStringBuffer("ui_saber2", saber, MAX_QPATH );
00915 }
00916 }
00917
00918 UI_SaberTypeForSaber( saber, saberTypeString );
00919 if ( saberTypeString[0] )
00920 {
00921 saberType = TranslateSaberType( saberTypeString );
00922 }
00923
00924 switch ( uiInfo.movesTitleIndex )
00925 {
00926 case 0:
00927 break;
00928 case 1:
00929 case 2:
00930 case 3:
00931 if ( saberType != SABER_SINGLE )
00932 {
00933 Q_strncpyz(saber,"single_1",MAX_QPATH);
00934 }
00935 break;
00936 case 4:
00937 if ( saberType != SABER_SINGLE )
00938 {
00939 Q_strncpyz(saber,"single_1",MAX_QPATH);
00940 }
00941 break;
00942 case 5:
00943 if ( saberType == SABER_SINGLE || saberType == SABER_NONE )
00944 {
00945 Q_strncpyz(saber,"dual_1",MAX_QPATH);
00946 }
00947 break;
00948 }
00949
00950 }
00951
00952 void UI_SaberDrawBlades( itemDef_t *item, vec3_t origin, vec3_t angles )
00953 {
00954
00955 char saber[MAX_QPATH];
00956 int saberNum = 0;
00957 int saberModel = 0;
00958 int numSabers = 1;
00959
00960 if ( (item->flags&ITF_ISCHARACTER)
00961 && uiInfo.movesTitleIndex == 4 )
00962 {
00963 numSabers = 2;
00964 }
00965
00966 for ( saberNum = 0; saberNum < numSabers; saberNum++ )
00967 {
00968 if ( (item->flags&ITF_ISCHARACTER) )
00969 {
00970 UI_GetSaberForMenu( saber, saberNum );
00971 saberModel = saberNum + 1;
00972 }
00973 else if ( (item->flags&ITF_ISSABER) )
00974 {
00975 trap_Cvar_VariableStringBuffer("ui_saber", saber, sizeof(saber) );
00976 if ( !UI_SaberValidForPlayerInMP( saber ) )
00977 {
00978 trap_Cvar_Set( "ui_saber", "kyle" );
00979 trap_Cvar_VariableStringBuffer("ui_saber", saber, sizeof(saber) );
00980 }
00981 saberModel = 0;
00982 }
00983 else if ( (item->flags&ITF_ISSABER2) )
00984 {
00985 trap_Cvar_VariableStringBuffer("ui_saber2", saber, sizeof(saber) );
00986 if ( !UI_SaberValidForPlayerInMP( saber ) )
00987 {
00988 trap_Cvar_Set( "ui_saber2", "kyle" );
00989 trap_Cvar_VariableStringBuffer("ui_saber2", saber, sizeof(saber) );
00990 }
00991 saberModel = 0;
00992 }
00993 else
00994 {
00995 return;
00996 }
00997 if ( saber[0] )
00998 {
00999 saberType_t saberType;
01000 int curBlade = 0;
01001 int numBlades = UI_SaberNumBladesForSaber( saber );
01002 if ( numBlades )
01003 {
01004 char saberTypeString[MAX_QPATH]={0};
01005 UI_SaberTypeForSaber( saber, saberTypeString );
01006 saberType = TranslateSaberType( saberTypeString );
01007 for ( curBlade = 0; curBlade < numBlades; curBlade++ )
01008 {
01009 if ( UI_SaberShouldDrawBlade( saber, curBlade ) )
01010 {
01011 UI_SaberDrawBlade( item, saber, saberModel, saberType, origin, angles, curBlade );
01012 }
01013 }
01014 }
01015 }
01016 }
01017 }
01018
01019 void UI_SaberAttachToChar( itemDef_t *item )
01020 {
01021 int numSabers = 1;
01022 int saberNum = 0;
01023
01024 if ( trap_G2API_HasGhoul2ModelOnIndex(&(item->ghoul2),2) )
01025 {
01026 trap_G2API_RemoveGhoul2Model(&(item->ghoul2), 2);
01027 }
01028 if ( trap_G2API_HasGhoul2ModelOnIndex(&(item->ghoul2),1) )
01029 {
01030 trap_G2API_RemoveGhoul2Model(&(item->ghoul2), 1);
01031 }
01032
01033 if ( uiInfo.movesTitleIndex == 4 )
01034 {
01035 numSabers = 2;
01036 }
01037
01038 for ( saberNum = 0; saberNum < numSabers; saberNum++ )
01039 {
01040
01041 char modelPath[MAX_QPATH];
01042 char skinPath[MAX_QPATH];
01043 char saber[MAX_QPATH];
01044
01045 UI_GetSaberForMenu( saber, saberNum );
01046
01047 if ( UI_SaberModelForSaber( saber, modelPath ) )
01048 {
01049 int g2Saber = trap_G2API_InitGhoul2Model( &(item->ghoul2), modelPath, 0, 0, 0, 0, 0 );
01050 if ( g2Saber )
01051 {
01052 int boltNum;
01053
01054 if ( UI_SaberSkinForSaber( saber, skinPath ) )
01055 {
01056 int g2skin = trap_R_RegisterSkin(skinPath);
01057 trap_G2API_SetSkin( item->ghoul2, g2Saber, 0, g2skin );
01058 }
01059 else
01060 {
01061 trap_G2API_SetSkin( item->ghoul2, g2Saber, 0, 0 );
01062 }
01063 if ( saberNum == 0 )
01064 {
01065 boltNum = trap_G2API_AddBolt( item->ghoul2, 0, "*r_hand");
01066 }
01067 else
01068 {
01069 boltNum = trap_G2API_AddBolt( item->ghoul2, 0, "*l_hand");
01070 }
01071 trap_G2API_AttachG2Model( item->ghoul2, g2Saber, item->ghoul2, boltNum, 0);
01072 }
01073 }
01074 }
01075 }
01076
01077 #define MAX_SABER_HILTS 64
01078
01079
01080 void UI_SaberGetHiltInfo( const char *singleHilts[MAX_SABER_HILTS], const char *staffHilts[MAX_SABER_HILTS] )
01081 {
01082 int numSingleHilts = 0, numStaffHilts = 0;
01083 const char *saberName;
01084 const char *token;
01085 const char *p;
01086
01087
01088 p = SaberParms;
01089 COM_BeginParseSession("saberlist");
01090
01091
01092 while ( p )
01093 {
01094 token = COM_ParseExt( &p, qtrue );
01095 if ( token[0] == 0 )
01096 {
01097 continue;
01098 }
01099 saberName = String_Alloc( token );
01100
01101 SkipRestOfLine( &p );
01102
01103 if ( UI_ParseLiteralSilent( &p, "{" ) )
01104 {
01105 continue;
01106 }
01107
01108
01109 if ( !UI_SaberValidForPlayerInMP( saberName ) )
01110 {
01111 SkipBracedSection( &p );
01112 continue;
01113 }
01114
01115 if ( UI_IsSaberTwoHanded( saberName ) )
01116 {
01117 if ( numStaffHilts < MAX_SABER_HILTS-1 )
01118 {
01119 staffHilts[numStaffHilts++] = saberName;
01120 }
01121 else
01122 {
01123 Com_Printf( "WARNING: too many two-handed sabers, ignoring saber '%s'\n", saberName );
01124 }
01125 }
01126 else
01127 {
01128 if ( numSingleHilts < MAX_SABER_HILTS-1 )
01129 {
01130 singleHilts[numSingleHilts++] = saberName;
01131 }
01132 else
01133 {
01134 Com_Printf( "WARNING: too many one-handed sabers, ignoring saber '%s'\n", saberName );
01135 }
01136 }
01137
01138 SkipBracedSection( &p );
01139 }
01140
01141 singleHilts[numSingleHilts] = NULL;
01142 staffHilts[numStaffHilts] = NULL;
01143 }