00001
00002 #include "b_local.h"
00003 #include "b_public.h"
00004 #include "anims.h"
00005 #include "../ghoul2/G2.h"
00006
00007 extern qboolean NPCsPrecached;
00008
00009 #include "../namespace_begin.h"
00010 extern qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber );
00011 extern void WP_RemoveSaber( saberInfo_t *sabers, int saberNum );
00012 #include "../namespace_end.h"
00013
00014 stringID_table_t TeamTable[] =
00015 {
00016 ENUM2STRING(NPCTEAM_FREE),
00017 ENUM2STRING(NPCTEAM_PLAYER),
00018 ENUM2STRING(NPCTEAM_ENEMY),
00019 ENUM2STRING(NPCTEAM_NEUTRAL),
00020 "", -1
00021 };
00022
00023
00024 stringID_table_t ClassTable[] =
00025 {
00026 ENUM2STRING(CLASS_NONE),
00027 ENUM2STRING(CLASS_ATST),
00028 ENUM2STRING(CLASS_BARTENDER),
00029 ENUM2STRING(CLASS_BESPIN_COP),
00030 ENUM2STRING(CLASS_CLAW),
00031 ENUM2STRING(CLASS_COMMANDO),
00032 ENUM2STRING(CLASS_DESANN),
00033 ENUM2STRING(CLASS_FISH),
00034 ENUM2STRING(CLASS_FLIER2),
00035 ENUM2STRING(CLASS_GALAK),
00036 ENUM2STRING(CLASS_GLIDER),
00037 ENUM2STRING(CLASS_GONK),
00038 ENUM2STRING(CLASS_GRAN),
00039 ENUM2STRING(CLASS_HOWLER),
00040
00041 ENUM2STRING(CLASS_IMPERIAL),
00042 ENUM2STRING(CLASS_IMPWORKER),
00043 ENUM2STRING(CLASS_INTERROGATOR),
00044 ENUM2STRING(CLASS_JAN),
00045 ENUM2STRING(CLASS_JEDI),
00046 ENUM2STRING(CLASS_KYLE),
00047 ENUM2STRING(CLASS_LANDO),
00048 ENUM2STRING(CLASS_LIZARD),
00049 ENUM2STRING(CLASS_LUKE),
00050 ENUM2STRING(CLASS_MARK1),
00051 ENUM2STRING(CLASS_MARK2),
00052 ENUM2STRING(CLASS_GALAKMECH),
00053 ENUM2STRING(CLASS_MINEMONSTER),
00054 ENUM2STRING(CLASS_MONMOTHA),
00055 ENUM2STRING(CLASS_MORGANKATARN),
00056 ENUM2STRING(CLASS_MOUSE),
00057 ENUM2STRING(CLASS_MURJJ),
00058 ENUM2STRING(CLASS_PRISONER),
00059 ENUM2STRING(CLASS_PROBE),
00060 ENUM2STRING(CLASS_PROTOCOL),
00061 ENUM2STRING(CLASS_R2D2),
00062 ENUM2STRING(CLASS_R5D2),
00063 ENUM2STRING(CLASS_REBEL),
00064 ENUM2STRING(CLASS_REBORN),
00065 ENUM2STRING(CLASS_REELO),
00066 ENUM2STRING(CLASS_REMOTE),
00067 ENUM2STRING(CLASS_RODIAN),
00068 ENUM2STRING(CLASS_SEEKER),
00069 ENUM2STRING(CLASS_SENTRY),
00070 ENUM2STRING(CLASS_SHADOWTROOPER),
00071 ENUM2STRING(CLASS_STORMTROOPER),
00072 ENUM2STRING(CLASS_SWAMP),
00073 ENUM2STRING(CLASS_SWAMPTROOPER),
00074 ENUM2STRING(CLASS_TAVION),
00075 ENUM2STRING(CLASS_TRANDOSHAN),
00076 ENUM2STRING(CLASS_UGNAUGHT),
00077 ENUM2STRING(CLASS_JAWA),
00078 ENUM2STRING(CLASS_WEEQUAY),
00079 ENUM2STRING(CLASS_BOBAFETT),
00080
00081
00082 ENUM2STRING(CLASS_VEHICLE),
00083 ENUM2STRING(CLASS_RANCOR),
00084 ENUM2STRING(CLASS_WAMPA),
00085 "", -1
00086 };
00087
00088 stringID_table_t BSTable[] =
00089 {
00090 ENUM2STRING(BS_DEFAULT),
00091 ENUM2STRING(BS_ADVANCE_FIGHT),
00092 ENUM2STRING(BS_SLEEP),
00093 ENUM2STRING(BS_FOLLOW_LEADER),
00094 ENUM2STRING(BS_JUMP),
00095 ENUM2STRING(BS_SEARCH),
00096 ENUM2STRING(BS_WANDER),
00097 ENUM2STRING(BS_NOCLIP),
00098 ENUM2STRING(BS_REMOVE),
00099 ENUM2STRING(BS_CINEMATIC),
00100
00101 "", -1,
00102 };
00103
00104 #define stringIDExpand(str, strEnum) str, strEnum, ENUM2STRING(strEnum)
00105
00106 stringID_table_t BSETTable[] =
00107 {
00108 ENUM2STRING(BSET_SPAWN),
00109 ENUM2STRING(BSET_USE),
00110 ENUM2STRING(BSET_AWAKE),
00111 ENUM2STRING(BSET_ANGER),
00112 ENUM2STRING(BSET_ATTACK),
00113 ENUM2STRING(BSET_VICTORY),
00114 ENUM2STRING(BSET_LOSTENEMY),
00115 ENUM2STRING(BSET_PAIN),
00116 ENUM2STRING(BSET_FLEE),
00117 ENUM2STRING(BSET_DEATH),
00118 ENUM2STRING(BSET_DELAYED),
00119 ENUM2STRING(BSET_BLOCKED),
00120 ENUM2STRING(BSET_BUMPED),
00121 ENUM2STRING(BSET_STUCK),
00122 ENUM2STRING(BSET_FFIRE),
00123 ENUM2STRING(BSET_FFDEATH),
00124 stringIDExpand("", BSET_INVALID),
00125 "", -1,
00126 };
00127
00128 #include "../namespace_begin.h"
00129 extern stringID_table_t WPTable[];
00130 extern stringID_table_t FPTable[];
00131 #include "../namespace_end.h"
00132
00133 char *TeamNames[TEAM_NUM_TEAMS] =
00134 {
00135 "",
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 "player",
00151 "enemy",
00152 "neutral"
00153 };
00154
00155
00156 char *ClassNames[CLASS_NUM_CLASSES] =
00157 {
00158 "",
00159 "atst",
00160 "bartender",
00161 "bespin_cop",
00162 "claw",
00163 "commando",
00164 "desann",
00165 "fish",
00166 "flier2",
00167 "galak",
00168 "glider",
00169 "gonk",
00170 "gran",
00171 "howler",
00172 "imperial",
00173 "impworker",
00174 "interrogator",
00175 "jan",
00176 "jedi",
00177 "kyle",
00178 "lando",
00179 "lizard",
00180 "luke",
00181 "mark1",
00182 "mark2",
00183 "galak_mech",
00184 "minemonster",
00185 "monmotha",
00186 "morgankatarn",
00187 "mouse",
00188 "murjj",
00189 "prisoner",
00190 "probe",
00191 "protocol",
00192 "r2d2",
00193 "r5d2",
00194 "rebel",
00195 "reborn",
00196 "reelo",
00197 "remote",
00198 "rodian",
00199 "seeker",
00200 "sentry",
00201 "shadowtrooper",
00202 "stormtrooper",
00203 "swamp",
00204 "swamptrooper",
00205 "tavion",
00206 "trandoshan",
00207 "ugnaught",
00208 "weequay",
00209 "bobafett",
00210 "vehicle",
00211 "rancor",
00212 "wampa",
00213 };
00214
00215
00216
00217
00218
00219
00220 int NPC_ReactionTime ( void )
00221 {
00222 return 200 * ( 6 - NPCInfo->stats.reactions );
00223 }
00224
00225
00226
00227
00228
00229 #include "../namespace_begin.h"
00230 extern qboolean BG_ParseLiteral( const char **data, const char *string );
00231 #include "../namespace_end.h"
00232
00233
00234
00235
00236 #define MAX_NPC_DATA_SIZE 0x20000
00237 char NPCParms[MAX_NPC_DATA_SIZE];
00238 char NPCFile[MAX_QPATH];
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 static rank_t TranslateRankName( const char *name )
00288 {
00289 if ( !Q_stricmp( name, "civilian" ) )
00290 {
00291 return RANK_CIVILIAN;
00292 }
00293
00294 if ( !Q_stricmp( name, "crewman" ) )
00295 {
00296 return RANK_CREWMAN;
00297 }
00298
00299 if ( !Q_stricmp( name, "ensign" ) )
00300 {
00301 return RANK_ENSIGN;
00302 }
00303
00304 if ( !Q_stricmp( name, "ltjg" ) )
00305 {
00306 return RANK_LT_JG;
00307 }
00308
00309 if ( !Q_stricmp( name, "lt" ) )
00310 {
00311 return RANK_LT;
00312 }
00313
00314 if ( !Q_stricmp( name, "ltcomm" ) )
00315 {
00316 return RANK_LT_COMM;
00317 }
00318
00319 if ( !Q_stricmp( name, "commander" ) )
00320 {
00321 return RANK_COMMANDER;
00322 }
00323
00324 if ( !Q_stricmp( name, "captain" ) )
00325 {
00326 return RANK_CAPTAIN;
00327 }
00328
00329 return RANK_CIVILIAN;
00330 }
00331
00332 #include "../namespace_begin.h"
00333 extern saber_colors_t TranslateSaberColor( const char *name );
00334 #include "../namespace_end.h"
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING
00398 void SpewDebugStuffToFile(animation_t *anims)
00399 {
00400 char BGPAFtext[40000];
00401 fileHandle_t f;
00402 int i = 0;
00403
00404 trap_FS_FOpenFile("file_of_debug_stuff_SP.txt", &f, FS_WRITE);
00405
00406 if (!f)
00407 {
00408 return;
00409 }
00410
00411 BGPAFtext[0] = 0;
00412
00413 while (i < MAX_ANIMATIONS)
00414 {
00415 strcat(BGPAFtext, va("%i %i\n", i, anims[i].frameLerp));
00416 i++;
00417 }
00418
00419 trap_FS_Write(BGPAFtext, strlen(BGPAFtext), f);
00420 trap_FS_FCloseFile(f);
00421 }
00422 #endif
00423
00424 qboolean G_ParseAnimFileSet( const char *filename, const char *animCFG, int *animFileIndex )
00425 {
00426 *animFileIndex = BG_ParseAnimationFile(filename, NULL, qfalse);
00427
00428
00429 if (*animFileIndex == -1)
00430 {
00431 return qfalse;
00432 }
00433
00434
00435
00436 return qtrue;
00437 }
00438
00439 void NPC_PrecacheAnimationCFG( const char *NPC_type )
00440 {
00441 #if 0 //rwwFIXMEFIXME: Actually precache stuff here.
00442 char filename[MAX_QPATH];
00443 const char *token;
00444 const char *value;
00445 const char *p;
00446 int junk;
00447
00448 if ( !Q_stricmp( "random", NPC_type ) )
00449 {
00450 return;
00451 }
00452
00453 p = NPCParms;
00454 COM_BeginParseSession(NPCFile);
00455
00456
00457 while ( p )
00458 {
00459 token = COM_ParseExt( &p, qtrue );
00460 if ( token[0] == 0 )
00461 return;
00462
00463 if ( !Q_stricmp( token, NPC_type ) )
00464 {
00465 break;
00466 }
00467
00468 SkipBracedSection( &p );
00469 }
00470
00471 if ( !p )
00472 {
00473 return;
00474 }
00475
00476 if ( BG_ParseLiteral( &p, "{" ) )
00477 {
00478 return;
00479 }
00480
00481
00482 while ( 1 )
00483 {
00484 token = COM_ParseExt( &p, qtrue );
00485 if ( !token[0] )
00486 {
00487 Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", NPC_type );
00488 return;
00489 }
00490
00491 if ( !Q_stricmp( token, "}" ) )
00492 {
00493 break;
00494 }
00495
00496
00497 if ( !Q_stricmp( token, "legsmodel" ) )
00498 {
00499 if ( COM_ParseString( &p, &value ) )
00500 {
00501 continue;
00502 }
00503
00504 Q_strncpyz( filename, value, sizeof( filename ) );
00505 G_ParseAnimFileSet( filename, filename, &junk );
00506 return;
00507 }
00508
00509
00510 if ( !Q_stricmp( token, "playerModel" ) )
00511 {
00512 if ( COM_ParseString( &p, &value ) )
00513 {
00514 continue;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 }
00546 }
00547 #endif
00548 }
00549
00550 extern int NPC_WeaponsForTeam( team_t team, int spawnflags, const char *NPC_type );
00551 void NPC_PrecacheWeapons( team_t playerTeam, int spawnflags, char *NPCtype )
00552 {
00553 int weapons = NPC_WeaponsForTeam( playerTeam, spawnflags, NPCtype );
00554 int curWeap;
00555
00556 for ( curWeap = WP_SABER; curWeap < WP_NUM_WEAPONS; curWeap++ )
00557 {
00558 if (weapons & (1 << curWeap))
00559 {
00560 RegisterItem(BG_FindItemForWeapon((weapon_t)curWeap));
00561 }
00562 }
00563
00564 #if 0 //rwwFIXMEFIXME: actually precache weapons here
00565 int weapons = NPC_WeaponsForTeam( playerTeam, spawnflags, NPCtype );
00566 gitem_t *item;
00567 for ( int curWeap = WP_SABER; curWeap < WP_NUM_WEAPONS; curWeap++ )
00568 {
00569 if ( (weapons & ( 1 << curWeap )) )
00570 {
00571 item = FindItemForWeapon( ((weapon_t)(curWeap)) );
00572 CG_RegisterItemSounds( (item-bg_itemlist) );
00573 CG_RegisterItemVisuals( (item-bg_itemlist) );
00574
00575
00576 char weaponModel[64];
00577
00578 strcpy (weaponModel, weaponData[curWeap].weaponMdl);
00579 if (char *spot = strstr(weaponModel, ".md3") ) {
00580 *spot = 0;
00581 spot = strstr(weaponModel, "_w");
00582 if (!spot) {
00583 strcat (weaponModel, "_w");
00584 }
00585 strcat (weaponModel, ".glm");
00586 }
00587 gi.G2API_PrecacheGhoul2Model( weaponModel );
00588 }
00589 }
00590 #endif
00591 }
00592
00593
00594
00595
00596
00597
00598
00599 void NPC_Precache ( gentity_t *spawner )
00600 {
00601 npcteam_t playerTeam = NPCTEAM_FREE;
00602 const char *token;
00603 const char *value;
00604 const char *p;
00605 char *patch;
00606 char sound[MAX_QPATH];
00607 qboolean md3Model = qfalse;
00608 char playerModel[MAX_QPATH];
00609 char customSkin[MAX_QPATH];
00610
00611 if ( !Q_stricmp( "random", spawner->NPC_type ) )
00612 {
00613 return;
00614 }
00615 strcpy(customSkin,"default");
00616
00617 p = NPCParms;
00618 COM_BeginParseSession(NPCFile);
00619
00620
00621 while ( p )
00622 {
00623 token = COM_ParseExt( &p, qtrue );
00624 if ( token[0] == 0 )
00625 return;
00626
00627 if ( !Q_stricmp( token, spawner->NPC_type ) )
00628 {
00629 break;
00630 }
00631
00632 SkipBracedSection( &p );
00633 }
00634
00635 if ( !p )
00636 {
00637 return;
00638 }
00639
00640 if ( BG_ParseLiteral( &p, "{" ) )
00641 {
00642 return;
00643 }
00644
00645
00646 while ( 1 )
00647 {
00648 token = COM_ParseExt( &p, qtrue );
00649 if ( !token[0] )
00650 {
00651 Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", spawner->NPC_type );
00652 return;
00653 }
00654
00655 if ( !Q_stricmp( token, "}" ) )
00656 {
00657 break;
00658 }
00659
00660
00661 if ( !Q_stricmp( token, "headmodel" ) )
00662 {
00663 if ( COM_ParseString( &p, &value ) )
00664 {
00665 continue;
00666 }
00667
00668 if(!Q_stricmp("none", value))
00669 {
00670 }
00671 else
00672 {
00673
00674 }
00675 md3Model = qtrue;
00676 continue;
00677 }
00678
00679
00680 if ( !Q_stricmp( token, "torsomodel" ) )
00681 {
00682 if ( COM_ParseString( &p, &value ) )
00683 {
00684 continue;
00685 }
00686
00687 if(!Q_stricmp("none", value))
00688 {
00689 }
00690 else
00691 {
00692
00693 }
00694 md3Model = qtrue;
00695 continue;
00696 }
00697
00698
00699 if ( !Q_stricmp( token, "legsmodel" ) )
00700 {
00701 if ( COM_ParseString( &p, &value ) )
00702 {
00703 continue;
00704 }
00705
00706 md3Model = qtrue;
00707 continue;
00708 }
00709
00710
00711 if ( !Q_stricmp( token, "playerModel" ) )
00712 {
00713 if ( COM_ParseString( &p, &value ) )
00714 {
00715 continue;
00716 }
00717 Q_strncpyz( playerModel, value, sizeof(playerModel));
00718 md3Model = qfalse;
00719 continue;
00720 }
00721
00722
00723 if ( !Q_stricmp( token, "customSkin" ) )
00724 {
00725 if ( COM_ParseString( &p, &value ) )
00726 {
00727 continue;
00728 }
00729 Q_strncpyz( customSkin, value, sizeof(customSkin));
00730 continue;
00731 }
00732
00733
00734 if ( !Q_stricmp( token, "playerTeam" ) )
00735 {
00736 char tk[4096];
00737
00738 if ( COM_ParseString( &p, &value ) )
00739 {
00740 continue;
00741 }
00742
00743 Com_sprintf(tk, sizeof(tk), "NPC%s", token);
00744 playerTeam = (team_t)GetIDForString( TeamTable, tk );
00745 continue;
00746 }
00747
00748
00749
00750 if ( !Q_stricmp( token, "snd" ) ) {
00751 if ( COM_ParseString( &p, &value ) ) {
00752 continue;
00753 }
00754 if ( !(spawner->r.svFlags&SVF_NO_BASIC_SOUNDS) )
00755 {
00756
00757 Q_strncpyz( sound, value, sizeof( sound ) );
00758 patch = strstr( sound, "/" );
00759 if ( patch )
00760 {
00761 *patch = 0;
00762 }
00763 spawner->s.csSounds_Std = G_SoundIndex( va("*$%s", sound) );
00764 }
00765 continue;
00766 }
00767
00768
00769 if ( !Q_stricmp( token, "sndcombat" ) ) {
00770 if ( COM_ParseString( &p, &value ) ) {
00771 continue;
00772 }
00773 if ( !(spawner->r.svFlags&SVF_NO_COMBAT_SOUNDS) )
00774 {
00775
00776 Q_strncpyz( sound, value, sizeof( sound ) );
00777 patch = strstr( sound, "/" );
00778 if ( patch )
00779 {
00780 *patch = 0;
00781 }
00782 spawner->s.csSounds_Combat = G_SoundIndex( va("*$%s", sound) );
00783 }
00784 continue;
00785 }
00786
00787
00788 if ( !Q_stricmp( token, "sndextra" ) ) {
00789 if ( COM_ParseString( &p, &value ) ) {
00790 continue;
00791 }
00792 if ( !(spawner->r.svFlags&SVF_NO_EXTRA_SOUNDS) )
00793 {
00794
00795 Q_strncpyz( sound, value, sizeof( sound ) );
00796 patch = strstr( sound, "/" );
00797 if ( patch )
00798 {
00799 *patch = 0;
00800 }
00801 spawner->s.csSounds_Extra = G_SoundIndex( va("*$%s", sound) );
00802 }
00803 continue;
00804 }
00805
00806
00807 if ( !Q_stricmp( token, "sndjedi" ) ) {
00808 if ( COM_ParseString( &p, &value ) ) {
00809 continue;
00810 }
00811 if ( !(spawner->r.svFlags&SVF_NO_EXTRA_SOUNDS) )
00812 {
00813
00814 Q_strncpyz( sound, value, sizeof( sound ) );
00815 patch = strstr( sound, "/" );
00816 if ( patch )
00817 {
00818 *patch = 0;
00819 }
00820 spawner->s.csSounds_Jedi = G_SoundIndex( va("*$%s", sound) );
00821 }
00822 continue;
00823 }
00824
00825 if (!Q_stricmp(token, "weapon"))
00826 {
00827 int curWeap;
00828
00829 if (COM_ParseString(&p, &value))
00830 {
00831 continue;
00832 }
00833
00834 curWeap = GetIDForString( WPTable, value );
00835
00836 if (curWeap > WP_NONE && curWeap < WP_NUM_WEAPONS)
00837 {
00838 RegisterItem(BG_FindItemForWeapon((weapon_t)curWeap));
00839 }
00840 continue;
00841 }
00842 }
00843
00844
00845 if ( !spawner->client || spawner->client->NPC_class != CLASS_VEHICLE )
00846 {
00847 if ( md3Model )
00848 {
00849 Com_Printf("MD3 model using NPCs are not supported in MP\n");
00850 }
00851 else
00852 {
00853
00854 char modelName[MAX_QPATH];
00855
00856 Com_sprintf(modelName, sizeof(modelName), "models/players/%s/model.glm", playerModel);
00857 if (customSkin[0])
00858 {
00859 strcat( modelName, va("*%s", customSkin) );
00860 }
00861
00862 G_ModelIndex(modelName);
00863 }
00864 }
00865
00866
00867 NPC_PrecacheWeapons( playerTeam, spawner->spawnflags, spawner->NPC_type );
00868
00869
00870
00871
00872
00873 }
00874
00875 #if 0
00876 void NPC_BuildRandom( gentity_t *NPC )
00877 {
00878 int sex, color, head;
00879
00880 sex = Q_irand(0, 2);
00881 color = Q_irand(0, 2);
00882 switch( sex )
00883 {
00884 case 0:
00885 head = Q_irand(0, 2);
00886 switch( head )
00887 {
00888 default:
00889 case 0:
00890 Q_strncpyz( NPC->client->renderInfo.headModelName, "garren", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00891 break;
00892 case 1:
00893 Q_strncpyz( NPC->client->renderInfo.headModelName, "garren/salma", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00894 break;
00895 case 2:
00896 Q_strncpyz( NPC->client->renderInfo.headModelName, "garren/mackey", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00897 color = Q_irand(3, 5);
00898 break;
00899 }
00900 switch( color )
00901 {
00902 default:
00903 case 0:
00904 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale/gold", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00905 break;
00906 case 1:
00907 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00908 break;
00909 case 2:
00910 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale/blue", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00911 break;
00912 case 3:
00913 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale/aframG", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00914 break;
00915 case 4:
00916 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale/aframR", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00917 break;
00918 case 5:
00919 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewfemale/aframB", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00920 break;
00921 }
00922 Q_strncpyz( NPC->client->renderInfo.legsModelName, "crewfemale", sizeof(NPC->client->renderInfo.legsModelName), qtrue );
00923 break;
00924 default:
00925 case 1:
00926 case 2:
00927 head = Q_irand(0, 4);
00928 switch( head )
00929 {
00930 default:
00931 case 0:
00932 Q_strncpyz( NPC->client->renderInfo.headModelName, "chakotay/nelson", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00933 break;
00934 case 1:
00935 Q_strncpyz( NPC->client->renderInfo.headModelName, "paris/chase", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00936 break;
00937 case 2:
00938 Q_strncpyz( NPC->client->renderInfo.headModelName, "doctor/pasty", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00939 break;
00940 case 3:
00941 Q_strncpyz( NPC->client->renderInfo.headModelName, "kim/durk", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00942 break;
00943 case 4:
00944 Q_strncpyz( NPC->client->renderInfo.headModelName, "paris/kray", sizeof(NPC->client->renderInfo.headModelName), qtrue );
00945 break;
00946 }
00947 switch( color )
00948 {
00949 default:
00950 case 0:
00951 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewthin/red", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00952 break;
00953 case 1:
00954 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewthin", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00955 break;
00956 case 2:
00957 Q_strncpyz( NPC->client->renderInfo.torsoModelName, "crewthin/blue", sizeof(NPC->client->renderInfo.torsoModelName), qtrue );
00958 break;
00959
00960 }
00961 Q_strncpyz( NPC->client->renderInfo.legsModelName, "crewthin", sizeof(NPC->client->renderInfo.legsModelName), qtrue );
00962 break;
00963 }
00964
00965 NPC->s.modelScale[0] = NPC->s.modelScale[1] = NPC->s.modelScale[2] = Q_irand(87, 102)/100.0f;
00966
00967 NPC->NPC->rank = RANK_CREWMAN;
00968 NPC->client->playerTeam = NPC->s.teamowner = TEAM_PLAYER;
00969 NPC->client->clientInfo.customBasicSoundDir = "kyle";
00970 }
00971 #endif
00972
00973 extern void SetupGameGhoul2Model(gentity_t *ent, char *modelname, char *skinName);
00974 qboolean NPC_ParseParms( const char *NPCName, gentity_t *NPC )
00975 {
00976 const char *token;
00977 const char *value;
00978 const char *p;
00979 int n;
00980 float f;
00981 char *patch;
00982 char sound[MAX_QPATH];
00983 char playerModel[MAX_QPATH];
00984 char customSkin[MAX_QPATH];
00985 renderInfo_t *ri = &NPC->client->renderInfo;
00986 gNPCstats_t *stats = NULL;
00987 qboolean md3Model = qtrue;
00988 char surfOff[1024];
00989 char surfOn[1024];
00990 qboolean parsingPlayer = qfalse;
00991 vec3_t playerMins;
00992 vec3_t playerMaxs;
00993 int npcSaber1 = 0;
00994 int npcSaber2 = 0;
00995
00996 VectorSet(playerMins, -15, -15, DEFAULT_MINS_2);
00997 VectorSet(playerMaxs, 15, 15, DEFAULT_MAXS_2);
00998
00999 strcpy(customSkin,"default");
01000 if ( !NPCName || !NPCName[0])
01001 {
01002 NPCName = "Player";
01003 }
01004
01005 if ( !NPC->s.number && NPC->client != NULL )
01006 {
01007 parsingPlayer = qtrue;
01008 }
01009
01010 if ( NPC->NPC )
01011 {
01012 stats = &NPC->NPC->stats;
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 stats->aggression = 3;
01025 stats->aim = 3;
01026 stats->earshot = 1024;
01027 stats->evasion = 3;
01028 stats->hfov = 90;
01029 stats->intelligence = 3;
01030 stats->move = 3;
01031 stats->reactions = 3;
01032 stats->vfov = 60;
01033 stats->vigilance = 0.1f;
01034 stats->visrange = 1024;
01035
01036 stats->health = 0;
01037
01038 stats->yawSpeed = 90;
01039 stats->walkSpeed = 90;
01040 stats->runSpeed = 300;
01041 stats->acceleration = 15;
01042 }
01043 else
01044 {
01045 stats = NULL;
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055 memset( (char *)surfOff, 0, sizeof(surfOff) );
01056 memset( (char *)surfOn, 0, sizeof(surfOn) );
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 ri->headYawRangeLeft = 80;
01070 ri->headYawRangeRight = 80;
01071 ri->headPitchRangeUp = 45;
01072 ri->headPitchRangeDown = 45;
01073 ri->torsoYawRangeLeft = 60;
01074 ri->torsoYawRangeRight = 60;
01075 ri->torsoPitchRangeUp = 30;
01076 ri->torsoPitchRangeDown = 50;
01077
01078 VectorCopy(playerMins, NPC->r.mins);
01079 VectorCopy(playerMaxs, NPC->r.maxs);
01080 NPC->client->ps.crouchheight = CROUCH_MAXS_2;
01081 NPC->client->ps.standheight = DEFAULT_MAXS_2;
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 NPC->client->ps.customRGBA[0]=255;
01097 NPC->client->ps.customRGBA[1]=255;
01098 NPC->client->ps.customRGBA[2]=255;
01099 NPC->client->ps.customRGBA[3]=255;
01100
01101 if ( !Q_stricmp( "random", NPCName ) )
01102 {
01103
01104 Com_Printf("RANDOM NPC NOT SUPPORTED IN MP\n");
01105 return qfalse;
01106 }
01107 else
01108 {
01109 int fp;
01110
01111 p = NPCParms;
01112 COM_BeginParseSession(NPCFile);
01113
01114
01115 while ( p )
01116 {
01117 token = COM_ParseExt( &p, qtrue );
01118 if ( token[0] == 0 )
01119 {
01120 return qfalse;
01121 }
01122
01123 if ( !Q_stricmp( token, NPCName ) )
01124 {
01125 break;
01126 }
01127
01128 SkipBracedSection( &p );
01129 }
01130 if ( !p )
01131 {
01132 return qfalse;
01133 }
01134
01135 if ( BG_ParseLiteral( &p, "{" ) )
01136 {
01137 return qfalse;
01138 }
01139
01140
01141 while ( 1 )
01142 {
01143 token = COM_ParseExt( &p, qtrue );
01144 if ( !token[0] )
01145 {
01146 Com_Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing '%s'\n", NPCName );
01147 return qfalse;
01148 }
01149
01150 if ( !Q_stricmp( token, "}" ) )
01151 {
01152 break;
01153 }
01154
01155
01156 if ( !Q_stricmp( token, "customRGBA" ) )
01157 {
01158 if ( COM_ParseString( &p, &value ) )
01159 {
01160 continue;
01161 }
01162 if ( !Q_stricmp( value, "random") )
01163 {
01164 NPC->client->ps.customRGBA[0]=Q_irand(0,255);
01165 NPC->client->ps.customRGBA[1]=Q_irand(0,255);
01166 NPC->client->ps.customRGBA[2]=Q_irand(0,255);
01167 NPC->client->ps.customRGBA[3]=255;
01168 }
01169 else
01170 {
01171 NPC->client->ps.customRGBA[0]=atoi(value);
01172
01173 if ( COM_ParseInt( &p, &n ) )
01174 {
01175 continue;
01176 }
01177 NPC->client->ps.customRGBA[1]=n;
01178
01179 if ( COM_ParseInt( &p, &n ) )
01180 {
01181 continue;
01182 }
01183 NPC->client->ps.customRGBA[2]=n;
01184
01185 if ( COM_ParseInt( &p, &n ) )
01186 {
01187 continue;
01188 }
01189 NPC->client->ps.customRGBA[3]=n;
01190 }
01191 continue;
01192 }
01193
01194
01195 if ( !Q_stricmp( token, "headmodel" ) )
01196 {
01197 if ( COM_ParseString( &p, &value ) )
01198 {
01199 continue;
01200 }
01201
01202 if(!Q_stricmp("none", value))
01203 {
01204
01205 ri->headYawRangeLeft =
01206 ri->headYawRangeRight =
01207 ri->headPitchRangeUp =
01208 ri->headPitchRangeDown = 0;
01209 }
01210 continue;
01211 }
01212
01213
01214 if ( !Q_stricmp( token, "torsomodel" ) )
01215 {
01216 if ( COM_ParseString( &p, &value ) )
01217 {
01218 continue;
01219 }
01220
01221 if(!Q_stricmp("none", value))
01222 {
01223
01224 ri->torsoYawRangeLeft =
01225 ri->torsoYawRangeRight =
01226 ri->torsoPitchRangeUp =
01227 ri->torsoPitchRangeDown = 0;
01228 }
01229 continue;
01230 }
01231
01232
01233 if ( !Q_stricmp( token, "legsmodel" ) )
01234 {
01235 if ( COM_ParseString( &p, &value ) )
01236 {
01237 continue;
01238 }
01239
01240
01241
01242
01243
01244 continue;
01245 }
01246
01247
01248 if ( !Q_stricmp( token, "playerModel" ) )
01249 {
01250 if ( COM_ParseString( &p, &value ) )
01251 {
01252 continue;
01253 }
01254 Q_strncpyz( playerModel, value, sizeof(playerModel));
01255 md3Model = qfalse;
01256 continue;
01257 }
01258
01259
01260 if ( !Q_stricmp( token, "customSkin" ) )
01261 {
01262 if ( COM_ParseString( &p, &value ) )
01263 {
01264 continue;
01265 }
01266 Q_strncpyz( customSkin, value, sizeof(customSkin));
01267 continue;
01268 }
01269
01270
01271 if ( !Q_stricmp( token, "surfOff" ) )
01272 {
01273 if ( COM_ParseString( &p, &value ) )
01274 {
01275 continue;
01276 }
01277 if ( surfOff[0] )
01278 {
01279 Q_strcat( (char *)surfOff, sizeof(surfOff), "," );
01280 Q_strcat( (char *)surfOff, sizeof(surfOff), value );
01281 }
01282 else
01283 {
01284 Q_strncpyz( surfOff, value, sizeof(surfOff));
01285 }
01286 continue;
01287 }
01288
01289
01290 if ( !Q_stricmp( token, "surfOn" ) )
01291 {
01292 if ( COM_ParseString( &p, &value ) )
01293 {
01294 continue;
01295 }
01296 if ( surfOn[0] )
01297 {
01298 Q_strcat( (char *)surfOn, sizeof(surfOn), "," );
01299 Q_strcat( (char *)surfOn, sizeof(surfOn), value );
01300 }
01301 else
01302 {
01303 Q_strncpyz( surfOn, value, sizeof(surfOn));
01304 }
01305 continue;
01306 }
01307
01308
01309 if ( !Q_stricmp( token, "headYawRangeLeft" ) )
01310 {
01311 if ( COM_ParseInt( &p, &n ) )
01312 {
01313 SkipRestOfLine( &p );
01314 continue;
01315 }
01316 if ( n < 0 )
01317 {
01318 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01319 continue;
01320 }
01321 ri->headYawRangeLeft = n;
01322 continue;
01323 }
01324
01325
01326 if ( !Q_stricmp( token, "headYawRangeRight" ) )
01327 {
01328 if ( COM_ParseInt( &p, &n ) )
01329 {
01330 SkipRestOfLine( &p );
01331 continue;
01332 }
01333 if ( n < 0 )
01334 {
01335 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01336 continue;
01337 }
01338 ri->headYawRangeRight = n;
01339 continue;
01340 }
01341
01342
01343 if ( !Q_stricmp( token, "headPitchRangeUp" ) )
01344 {
01345 if ( COM_ParseInt( &p, &n ) )
01346 {
01347 SkipRestOfLine( &p );
01348 continue;
01349 }
01350 if ( n < 0 )
01351 {
01352 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01353 continue;
01354 }
01355 ri->headPitchRangeUp = n;
01356 continue;
01357 }
01358
01359
01360 if ( !Q_stricmp( token, "headPitchRangeDown" ) )
01361 {
01362 if ( COM_ParseInt( &p, &n ) )
01363 {
01364 SkipRestOfLine( &p );
01365 continue;
01366 }
01367 if ( n < 0 )
01368 {
01369 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01370 continue;
01371 }
01372 ri->headPitchRangeDown = n;
01373 continue;
01374 }
01375
01376
01377 if ( !Q_stricmp( token, "torsoYawRangeLeft" ) )
01378 {
01379 if ( COM_ParseInt( &p, &n ) )
01380 {
01381 SkipRestOfLine( &p );
01382 continue;
01383 }
01384 if ( n < 0 )
01385 {
01386 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01387 continue;
01388 }
01389 ri->torsoYawRangeLeft = n;
01390 continue;
01391 }
01392
01393
01394 if ( !Q_stricmp( token, "torsoYawRangeRight" ) )
01395 {
01396 if ( COM_ParseInt( &p, &n ) )
01397 {
01398 SkipRestOfLine( &p );
01399 continue;
01400 }
01401 if ( n < 0 )
01402 {
01403 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01404 continue;
01405 }
01406 ri->torsoYawRangeRight = n;
01407 continue;
01408 }
01409
01410
01411 if ( !Q_stricmp( token, "torsoPitchRangeUp" ) )
01412 {
01413 if ( COM_ParseInt( &p, &n ) )
01414 {
01415 SkipRestOfLine( &p );
01416 continue;
01417 }
01418 if ( n < 0 )
01419 {
01420 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01421 continue;
01422 }
01423 ri->torsoPitchRangeUp = n;
01424 continue;
01425 }
01426
01427
01428 if ( !Q_stricmp( token, "torsoPitchRangeDown" ) )
01429 {
01430 if ( COM_ParseInt( &p, &n ) )
01431 {
01432 SkipRestOfLine( &p );
01433 continue;
01434 }
01435 if ( n < 0 )
01436 {
01437 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01438 continue;
01439 }
01440 ri->torsoPitchRangeDown = n;
01441 continue;
01442 }
01443
01444
01445 if ( !Q_stricmp( token, "scale" ) )
01446 {
01447 if ( COM_ParseInt( &p, &n ) )
01448 {
01449 SkipRestOfLine( &p );
01450 continue;
01451 }
01452 if ( n < 0 )
01453 {
01454 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01455 continue;
01456 }
01457 if (n != 100)
01458 {
01459 NPC->client->ps.iModelScale = n;
01460 if (n >= 1024)
01461 {
01462 Com_Printf("WARNING: MP does not support scaling up to or over 1024%\n");
01463 n = 1023;
01464 }
01465
01466 NPC->modelScale[0] = NPC->modelScale[1] = NPC->modelScale[2] = n/100.0f;
01467 }
01468 continue;
01469 }
01470
01471
01472 if ( !Q_stricmp( token, "scaleX" ) )
01473 {
01474 if ( COM_ParseInt( &p, &n ) )
01475 {
01476 SkipRestOfLine( &p );
01477 continue;
01478 }
01479 if ( n < 0 )
01480 {
01481 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01482 continue;
01483 }
01484 if (n != 100)
01485 {
01486 Com_Printf("MP doesn't support xyz scaling, use 'scale'.\n");
01487
01488 }
01489 continue;
01490 }
01491
01492
01493 if ( !Q_stricmp( token, "scaleY" ) )
01494 {
01495 if ( COM_ParseInt( &p, &n ) )
01496 {
01497 SkipRestOfLine( &p );
01498 continue;
01499 }
01500 if ( n < 0 )
01501 {
01502 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01503 continue;
01504 }
01505 if (n != 100)
01506 {
01507 Com_Printf("MP doesn't support xyz scaling, use 'scale'.\n");
01508
01509 }
01510 continue;
01511 }
01512
01513
01514 if ( !Q_stricmp( token, "scaleZ" ) )
01515 {
01516 if ( COM_ParseInt( &p, &n ) )
01517 {
01518 SkipRestOfLine( &p );
01519 continue;
01520 }
01521 if ( n < 0 )
01522 {
01523 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01524 continue;
01525 }
01526 if (n != 100)
01527 {
01528 Com_Printf("MP doesn't support xyz scaling, use 'scale'.\n");
01529
01530 }
01531 continue;
01532 }
01533
01534
01535 if ( !parsingPlayer )
01536 {
01537
01538 if ( !Q_stricmp( token, "aggression" ) ) {
01539 if ( COM_ParseInt( &p, &n ) ) {
01540 SkipRestOfLine( &p );
01541 continue;
01542 }
01543 if ( n < 1 || n > 5 ) {
01544 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01545 continue;
01546 }
01547 if ( NPC->NPC )
01548 {
01549 stats->aggression = n;
01550 }
01551 continue;
01552 }
01553
01554
01555 if ( !Q_stricmp( token, "aim" ) ) {
01556 if ( COM_ParseInt( &p, &n ) ) {
01557 SkipRestOfLine( &p );
01558 continue;
01559 }
01560 if ( n < 1 || n > 5 ) {
01561 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01562 continue;
01563 }
01564 if ( NPC->NPC )
01565 {
01566 stats->aim = n;
01567 }
01568 continue;
01569 }
01570
01571
01572 if ( !Q_stricmp( token, "earshot" ) ) {
01573 if ( COM_ParseFloat( &p, &f ) ) {
01574 SkipRestOfLine( &p );
01575 continue;
01576 }
01577 if ( f < 0.0f )
01578 {
01579 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01580 continue;
01581 }
01582 if ( NPC->NPC )
01583 {
01584 stats->earshot = f;
01585 }
01586 continue;
01587 }
01588
01589
01590 if ( !Q_stricmp( token, "evasion" ) )
01591 {
01592 if ( COM_ParseInt( &p, &n ) )
01593 {
01594 SkipRestOfLine( &p );
01595 continue;
01596 }
01597 if ( n < 1 || n > 5 )
01598 {
01599 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01600 continue;
01601 }
01602 if ( NPC->NPC )
01603 {
01604 stats->evasion = n;
01605 }
01606 continue;
01607 }
01608
01609
01610 if ( !Q_stricmp( token, "hfov" ) ) {
01611 if ( COM_ParseInt( &p, &n ) ) {
01612 SkipRestOfLine( &p );
01613 continue;
01614 }
01615 if ( n < 30 || n > 180 ) {
01616 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01617 continue;
01618 }
01619 if ( NPC->NPC )
01620 {
01621 stats->hfov = n;
01622 }
01623 continue;
01624 }
01625
01626
01627 if ( !Q_stricmp( token, "intelligence" ) ) {
01628 if ( COM_ParseInt( &p, &n ) ) {
01629 SkipRestOfLine( &p );
01630 continue;
01631 }
01632 if ( n < 1 || n > 5 ) {
01633 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01634 continue;
01635 }
01636 if ( NPC->NPC )
01637 {
01638 stats->intelligence = n;
01639 }
01640 continue;
01641 }
01642
01643
01644 if ( !Q_stricmp( token, "move" ) ) {
01645 if ( COM_ParseInt( &p, &n ) ) {
01646 SkipRestOfLine( &p );
01647 continue;
01648 }
01649 if ( n < 1 || n > 5 ) {
01650 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01651 continue;
01652 }
01653 if ( NPC->NPC )
01654 {
01655 stats->move = n;
01656 }
01657 continue;
01658 }
01659
01660
01661 if ( !Q_stricmp( token, "reactions" ) ) {
01662 if ( COM_ParseInt( &p, &n ) ) {
01663 SkipRestOfLine( &p );
01664 continue;
01665 }
01666 if ( n < 1 || n > 5 ) {
01667 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01668 continue;
01669 }
01670 if ( NPC->NPC )
01671 {
01672 stats->reactions = n;
01673 }
01674 continue;
01675 }
01676
01677
01678 if ( !Q_stricmp( token, "shootDistance" ) ) {
01679 if ( COM_ParseFloat( &p, &f ) ) {
01680 SkipRestOfLine( &p );
01681 continue;
01682 }
01683 if ( f < 0.0f )
01684 {
01685 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01686 continue;
01687 }
01688 if ( NPC->NPC )
01689 {
01690 stats->shootDistance = f;
01691 }
01692 continue;
01693 }
01694
01695
01696 if ( !Q_stricmp( token, "vfov" ) ) {
01697 if ( COM_ParseInt( &p, &n ) ) {
01698 SkipRestOfLine( &p );
01699 continue;
01700 }
01701 if ( n < 30 || n > 180 ) {
01702 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01703 continue;
01704 }
01705 if ( NPC->NPC )
01706 {
01707 stats->vfov = n / 2;
01708 }
01709 continue;
01710 }
01711
01712
01713 if ( !Q_stricmp( token, "vigilance" ) ) {
01714 if ( COM_ParseFloat( &p, &f ) ) {
01715 SkipRestOfLine( &p );
01716 continue;
01717 }
01718 if ( f < 0.0f )
01719 {
01720 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01721 continue;
01722 }
01723 if ( NPC->NPC )
01724 {
01725 stats->vigilance = f;
01726 }
01727 continue;
01728 }
01729
01730
01731 if ( !Q_stricmp( token, "visrange" ) ) {
01732 if ( COM_ParseFloat( &p, &f ) ) {
01733 SkipRestOfLine( &p );
01734 continue;
01735 }
01736 if ( f < 0.0f )
01737 {
01738 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01739 continue;
01740 }
01741 if ( NPC->NPC )
01742 {
01743 stats->visrange = f;
01744 }
01745 continue;
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 if ( !Q_stricmp( token, "rank" ) )
01761 {
01762 if ( COM_ParseString( &p, &value ) )
01763 {
01764 continue;
01765 }
01766 if ( NPC->NPC )
01767 {
01768 NPC->NPC->rank = TranslateRankName(value);
01769 }
01770 continue;
01771 }
01772 }
01773
01774
01775 if ( !Q_stricmp( token, "health" ) )
01776 {
01777 if ( COM_ParseInt( &p, &n ) )
01778 {
01779 SkipRestOfLine( &p );
01780 continue;
01781 }
01782 if ( n < 0 )
01783 {
01784 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
01785 continue;
01786 }
01787 if ( NPC->NPC )
01788 {
01789 stats->health = n;
01790 }
01791 else if ( parsingPlayer )
01792 {
01793 NPC->client->ps.stats[STAT_MAX_HEALTH] = NPC->client->pers.maxHealth = n;
01794 }
01795 continue;
01796 }
01797
01798
01799 if ( !Q_stricmp( token, "fullName" ) )
01800 {
01801 if ( COM_ParseString( &p, &value ) )
01802 {
01803 continue;
01804 }
01805 NPC->fullName = G_NewString(value);
01806 continue;
01807 }
01808
01809
01810 if ( !Q_stricmp( token, "playerTeam" ) )
01811 {
01812 char tk[4096];
01813
01814 if ( COM_ParseString( &p, &value ) )
01815 {
01816 continue;
01817 }
01818 Com_sprintf(tk, sizeof(tk), "NPC%s", token);
01819 NPC->client->playerTeam = NPC->s.teamowner = (team_t)GetIDForString( TeamTable, tk );
01820 continue;
01821 }
01822
01823
01824 if ( !Q_stricmp( token, "enemyTeam" ) )
01825 {
01826 char tk[4096];
01827
01828 if ( COM_ParseString( &p, &value ) )
01829 {
01830 continue;
01831 }
01832 Com_sprintf(tk, sizeof(tk), "NPC%s", token);
01833 NPC->client->enemyTeam = (team_t)GetIDForString( TeamTable, tk );
01834 continue;
01835 }
01836
01837
01838 if ( !Q_stricmp( token, "class" ) )
01839 {
01840 if ( COM_ParseString( &p, &value ) )
01841 {
01842 continue;
01843 }
01844 NPC->client->NPC_class = (class_t)GetIDForString( ClassTable, value );
01845 NPC->s.NPC_class = NPC->client->NPC_class;
01846
01847
01848 if ( NPC->client->NPC_class == CLASS_VEHICLE )
01849 {
01850 if ( !NPC->m_pVehicle )
01851 {
01852 Com_Printf ( S_COLOR_RED "ERROR: Tried to spawn a vehicle NPC (%s) without using NPC_Vehicle or 'NPC spawn vehicle <vehiclename>'!!! Bad, bad, bad! Shame on you!\n", NPCName );
01853 return qfalse;
01854 }
01855 md3Model = qfalse;
01856 }
01857
01858 continue;
01859 }
01860
01861
01862 if ( !Q_stricmp( token, "dismemberProbHead" ) ) {
01863 if ( COM_ParseInt( &p, &n ) ) {
01864 SkipRestOfLine( &p );
01865 continue;
01866 }
01867 if ( n < 0 )
01868 {
01869 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01870 continue;
01871 }
01872 if ( NPC->NPC )
01873 {
01874
01875
01876 }
01877 continue;
01878 }
01879
01880
01881 if ( !Q_stricmp( token, "dismemberProbArms" ) ) {
01882 if ( COM_ParseInt( &p, &n ) ) {
01883 SkipRestOfLine( &p );
01884 continue;
01885 }
01886 if ( n < 0 )
01887 {
01888 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01889 continue;
01890 }
01891 if ( NPC->NPC )
01892 {
01893
01894 }
01895 continue;
01896 }
01897
01898
01899 if ( !Q_stricmp( token, "dismemberProbHands" ) ) {
01900 if ( COM_ParseInt( &p, &n ) ) {
01901 SkipRestOfLine( &p );
01902 continue;
01903 }
01904 if ( n < 0 )
01905 {
01906 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01907 continue;
01908 }
01909 if ( NPC->NPC )
01910 {
01911
01912 }
01913 continue;
01914 }
01915
01916
01917 if ( !Q_stricmp( token, "dismemberProbWaist" ) ) {
01918 if ( COM_ParseInt( &p, &n ) ) {
01919 SkipRestOfLine( &p );
01920 continue;
01921 }
01922 if ( n < 0 )
01923 {
01924 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01925 continue;
01926 }
01927 if ( NPC->NPC )
01928 {
01929
01930 }
01931 continue;
01932 }
01933
01934
01935 if ( !Q_stricmp( token, "dismemberProbLegs" ) ) {
01936 if ( COM_ParseInt( &p, &n ) ) {
01937 SkipRestOfLine( &p );
01938 continue;
01939 }
01940 if ( n < 0 )
01941 {
01942 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
01943 continue;
01944 }
01945 if ( NPC->NPC )
01946 {
01947
01948 }
01949 continue;
01950 }
01951
01952
01953
01954 if ( !Q_stricmp( token, "width" ) )
01955 {
01956 if ( COM_ParseInt( &p, &n ) )
01957 {
01958 continue;
01959 }
01960
01961 NPC->r.mins[0] = NPC->r.mins[1] = -n;
01962 NPC->r.maxs[0] = NPC->r.maxs[1] = n;
01963 continue;
01964 }
01965
01966 if ( !Q_stricmp( token, "height" ) )
01967 {
01968 if ( COM_ParseInt( &p, &n ) )
01969 {
01970 continue;
01971 }
01972 if ( NPC->client->NPC_class == CLASS_VEHICLE
01973 && NPC->m_pVehicle
01974 && NPC->m_pVehicle->m_pVehicleInfo
01975 && NPC->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
01976 {
01977
01978
01979
01980 NPC->r.maxs[2] = NPC->client->ps.standheight = (n/2.0f);
01981 NPC->r.mins[2] = -NPC->r.maxs[2];
01982 NPC->s.origin[2] += (DEFAULT_MINS_2-NPC->r.mins[2])+0.125f;
01983 VectorCopy(NPC->s.origin, NPC->client->ps.origin);
01984 VectorCopy(NPC->s.origin, NPC->r.currentOrigin);
01985 G_SetOrigin( NPC, NPC->s.origin );
01986 trap_LinkEntity(NPC);
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 }
01999 else
02000 {
02001 NPC->r.mins[2] = DEFAULT_MINS_2;
02002 NPC->r.maxs[2] = NPC->client->ps.standheight = n + DEFAULT_MINS_2;
02003 }
02004 NPC->radius = n;
02005 continue;
02006 }
02007
02008 if ( !Q_stricmp( token, "crouchheight" ) )
02009 {
02010 if ( COM_ParseInt( &p, &n ) )
02011 {
02012 continue;
02013 }
02014
02015 NPC->client->ps.crouchheight = n + DEFAULT_MINS_2;
02016 continue;
02017 }
02018
02019 if ( !parsingPlayer )
02020 {
02021 if ( !Q_stricmp( token, "movetype" ) )
02022 {
02023 if ( COM_ParseString( &p, &value ) )
02024 {
02025 continue;
02026 }
02027 if ( Q_stricmp( "flyswim", value ) == 0 )
02028 {
02029 NPC->client->ps.eFlags2 |= EF2_FLYING;
02030 }
02031
02032
02033 continue;
02034 }
02035
02036
02037 if ( !Q_stricmp( token, "yawSpeed" ) ) {
02038 if ( COM_ParseInt( &p, &n ) ) {
02039 SkipRestOfLine( &p );
02040 continue;
02041 }
02042 if ( n <= 0) {
02043 Com_Printf( "bad %s in NPC '%s'\n", token, NPCName );
02044 continue;
02045 }
02046 if ( NPC->NPC )
02047 {
02048 stats->yawSpeed = ((float)(n));
02049 }
02050 continue;
02051 }
02052
02053
02054 if ( !Q_stricmp( token, "walkSpeed" ) )
02055 {
02056 if ( COM_ParseInt( &p, &n ) )
02057 {
02058 SkipRestOfLine( &p );
02059 continue;
02060 }
02061 if ( n < 0 )
02062 {
02063 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
02064 continue;
02065 }
02066 if ( NPC->NPC )
02067 {
02068 stats->walkSpeed = n;
02069 }
02070 continue;
02071 }
02072
02073
02074 if ( !Q_stricmp( token, "runSpeed" ) )
02075 {
02076 if ( COM_ParseInt( &p, &n ) )
02077 {
02078 SkipRestOfLine( &p );
02079 continue;
02080 }
02081 if ( n < 0 )
02082 {
02083 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
02084 continue;
02085 }
02086 if ( NPC->NPC )
02087 {
02088 stats->runSpeed = n;
02089 }
02090 continue;
02091 }
02092
02093
02094 if ( !Q_stricmp( token, "acceleration" ) )
02095 {
02096 if ( COM_ParseInt( &p, &n ) )
02097 {
02098 SkipRestOfLine( &p );
02099 continue;
02100 }
02101 if ( n < 0 )
02102 {
02103 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
02104 continue;
02105 }
02106 if ( NPC->NPC )
02107 {
02108 stats->acceleration = n;
02109 }
02110 continue;
02111 }
02112
02113 if ( !Q_stricmp( token, "sex" ) )
02114 {
02115 SkipRestOfLine( &p );
02116 continue;
02117 }
02118
02119
02120 if ( !Q_stricmp( token, "behavior" ) )
02121 {
02122 if ( COM_ParseInt( &p, &n ) )
02123 {
02124 SkipRestOfLine( &p );
02125 continue;
02126 }
02127 if ( n < BS_DEFAULT || n >= NUM_BSTATES )
02128 {
02129 Com_Printf( S_COLOR_YELLOW"WARNING: bad %s in NPC '%s'\n", token, NPCName );
02130 continue;
02131 }
02132 if ( NPC->NPC )
02133 {
02134 NPC->NPC->defaultBehavior = (bState_t)(n);
02135 }
02136 continue;
02137 }
02138 }
02139
02140
02141 if ( !Q_stricmp( token, "snd" ) )
02142 {
02143 if ( COM_ParseString( &p, &value ) )
02144 {
02145 continue;
02146 }
02147 if ( !(NPC->r.svFlags&SVF_NO_BASIC_SOUNDS) )
02148 {
02149
02150 Q_strncpyz( sound, value, sizeof( sound ) );
02151 patch = strstr( sound, "/" );
02152 if ( patch )
02153 {
02154 *patch = 0;
02155 }
02156
02157
02158 }
02159 continue;
02160 }
02161
02162
02163 if ( !Q_stricmp( token, "sndcombat" ) )
02164 {
02165 if ( COM_ParseString( &p, &value ) )
02166 {
02167 continue;
02168 }
02169 if ( !(NPC->r.svFlags&SVF_NO_COMBAT_SOUNDS) )
02170 {
02171
02172 Q_strncpyz( sound, value, sizeof( sound ) );
02173 patch = strstr( sound, "/" );
02174 if ( patch )
02175 {
02176 *patch = 0;
02177 }
02178
02179 }
02180 continue;
02181 }
02182
02183
02184 if ( !Q_stricmp( token, "sndextra" ) )
02185 {
02186 if ( COM_ParseString( &p, &value ) )
02187 {
02188 continue;
02189 }
02190 if ( !(NPC->r.svFlags&SVF_NO_EXTRA_SOUNDS) )
02191 {
02192
02193 Q_strncpyz( sound, value, sizeof( sound ) );
02194 patch = strstr( sound, "/" );
02195 if ( patch )
02196 {
02197 *patch = 0;
02198 }
02199
02200 }
02201 continue;
02202 }
02203
02204
02205 if ( !Q_stricmp( token, "sndjedi" ) )
02206 {
02207 if ( COM_ParseString( &p, &value ) )
02208 {
02209 continue;
02210 }
02211 if ( !(NPC->r.svFlags&SVF_NO_EXTRA_SOUNDS) )
02212 {
02213
02214 Q_strncpyz( sound, value, sizeof( sound ) );
02215 patch = strstr( sound, "/" );
02216 if ( patch )
02217 {
02218 *patch = 0;
02219 }
02220
02221 }
02222 continue;
02223 }
02224
02225
02226
02227 if ( !Q_stricmp( token, "weapon" ) )
02228 {
02229 int weap;
02230
02231 if ( COM_ParseString( &p, &value ) )
02232 {
02233 continue;
02234 }
02235
02236 weap = GetIDForString( WPTable, value );
02237 if ( weap >= WP_NONE && weap <= WP_NUM_WEAPONS )
02238 {
02239 NPC->client->ps.weapon = weap;
02240 NPC->client->ps.stats[STAT_WEAPONS] |= ( 1 << NPC->client->ps.weapon );
02241 if ( weap > WP_NONE )
02242 {
02243
02244 NPC->client->ps.ammo[weaponData[NPC->client->ps.weapon].ammoIndex] = 100;
02245 }
02246 }
02247 continue;
02248 }
02249
02250 if ( !parsingPlayer )
02251 {
02252
02253 if ( !Q_stricmp( token, "altFire" ) )
02254 {
02255 if ( COM_ParseInt( &p, &n ) )
02256 {
02257 SkipRestOfLine( &p );
02258 continue;
02259 }
02260 if ( NPC->NPC )
02261 {
02262 if ( n != 0 )
02263 {
02264 NPC->NPC->scriptFlags |= SCF_ALT_FIRE;
02265 }
02266 }
02267 continue;
02268 }
02269
02270 }
02271
02272
02273 fp = GetIDForString( FPTable, token );
02274 if ( fp >= FP_FIRST && fp < NUM_FORCE_POWERS )
02275 {
02276 if ( COM_ParseInt( &p, &n ) )
02277 {
02278 SkipRestOfLine( &p );
02279 continue;
02280 }
02281
02282
02283 if ( n > 5 )
02284 {
02285 n = 5;
02286 }
02287 else if ( n < 0 )
02288 {
02289 n = 0;
02290 }
02291 if ( n )
02292 {
02293 NPC->client->ps.fd.forcePowersKnown |= ( 1 << fp );
02294 }
02295 else
02296 {
02297 NPC->client->ps.fd.forcePowersKnown &= ~( 1 << fp );
02298 }
02299 NPC->client->ps.fd.forcePowerLevel[fp] = n;
02300 continue;
02301 }
02302
02303
02304 if ( !Q_stricmp( token, "forcePowerMax" ) )
02305 {
02306 if ( COM_ParseInt( &p, &n ) )
02307 {
02308 SkipRestOfLine( &p );
02309 continue;
02310 }
02311 NPC->client->ps.fd.forcePowerMax = n;
02312 continue;
02313 }
02314
02315
02316 if ( !Q_stricmp( token, "forceRegenRate" ) )
02317 {
02318 if ( COM_ParseInt( &p, &n ) )
02319 {
02320 SkipRestOfLine( &p );
02321 continue;
02322 }
02323
02324
02325 continue;
02326 }
02327
02328
02329 if ( !Q_stricmp( token, "forceRegenAmount" ) )
02330 {
02331 if ( COM_ParseInt( &p, &n ) )
02332 {
02333 SkipRestOfLine( &p );
02334 continue;
02335 }
02336
02337
02338 continue;
02339 }
02340
02341
02342
02343 if ( !Q_stricmp( token, "saber" ) )
02344 {
02345 char *saberName;
02346
02347 if ( COM_ParseString( &p, &value ) )
02348 {
02349 continue;
02350 }
02351
02352 saberName = (char *)BG_TempAlloc(4096);
02353 strcpy(saberName, value);
02354
02355 WP_SaberParseParms( saberName, &NPC->client->saber[0] );
02356 npcSaber1 = G_ModelIndex(va("@%s", saberName));
02357
02358 BG_TempFree(4096);
02359 continue;
02360 }
02361
02362
02363 if ( !Q_stricmp( token, "saber2" ) )
02364 {
02365 if ( COM_ParseString( &p, &value ) )
02366 {
02367 continue;
02368 }
02369
02370 if ( !(NPC->client->saber[0].saberFlags&SFL_TWO_HANDED) )
02371 {
02372 char *saberName = (char *)BG_TempAlloc(4096);
02373 strcpy(saberName, value);
02374
02375 WP_SaberParseParms( saberName, &NPC->client->saber[1] );
02376 if ( (NPC->client->saber[1].saberFlags&SFL_TWO_HANDED) )
02377 {
02378 WP_RemoveSaber( NPC->client->saber, 1 );
02379 }
02380 else
02381 {
02382
02383 npcSaber2 = G_ModelIndex(va("@%s", saberName));
02384 }
02385 BG_TempFree(4096);
02386 }
02387 continue;
02388 }
02389
02390
02391 if ( !Q_stricmp( token, "saberColor" ) )
02392 {
02393 if ( COM_ParseString( &p, &value ) )
02394 {
02395 continue;
02396 }
02397 if ( NPC->client )
02398 {
02399 saber_colors_t color = TranslateSaberColor( value );
02400 for ( n = 0; n < MAX_BLADES; n++ )
02401 {
02402 NPC->client->saber[0].blade[n].color = color;
02403 }
02404 }
02405 continue;
02406 }
02407
02408 if ( !Q_stricmp( token, "saberColor2" ) )
02409 {
02410 if ( COM_ParseString( &p, &value ) )
02411 {
02412 continue;
02413 }
02414 if ( NPC->client )
02415 {
02416 NPC->client->saber[0].blade[1].color = TranslateSaberColor( value );
02417 }
02418 continue;
02419 }
02420
02421 if ( !Q_stricmp( token, "saberColor3" ) )
02422 {
02423 if ( COM_ParseString( &p, &value ) )
02424 {
02425 continue;
02426 }
02427 if ( NPC->client )
02428 {
02429 NPC->client->saber[0].blade[2].color = TranslateSaberColor( value );
02430 }
02431 continue;
02432 }
02433
02434 if ( !Q_stricmp( token, "saberColor4" ) )
02435 {
02436 if ( COM_ParseString( &p, &value ) )
02437 {
02438 continue;
02439 }
02440 if ( NPC->client )
02441 {
02442 NPC->client->saber[0].blade[3].color = TranslateSaberColor( value );
02443 }
02444 continue;
02445 }
02446
02447 if ( !Q_stricmp( token, "saberColor5" ) )
02448 {
02449 if ( COM_ParseString( &p, &value ) )
02450 {
02451 continue;
02452 }
02453 if ( NPC->client )
02454 {
02455 NPC->client->saber[0].blade[4].color = TranslateSaberColor( value );
02456 }
02457 continue;
02458 }
02459
02460 if ( !Q_stricmp( token, "saberColor6" ) )
02461 {
02462 if ( COM_ParseString( &p, &value ) )
02463 {
02464 continue;
02465 }
02466 if ( NPC->client )
02467 {
02468 NPC->client->saber[0].blade[5].color = TranslateSaberColor( value );
02469 }
02470 continue;
02471 }
02472
02473 if ( !Q_stricmp( token, "saberColor7" ) )
02474 {
02475 if ( COM_ParseString( &p, &value ) )
02476 {
02477 continue;
02478 }
02479 if ( NPC->client )
02480 {
02481 NPC->client->saber[0].blade[6].color = TranslateSaberColor( value );
02482 }
02483 continue;
02484 }
02485
02486 if ( !Q_stricmp( token, "saberColor8" ) )
02487 {
02488 if ( COM_ParseString( &p, &value ) )
02489 {
02490 continue;
02491 }
02492 if ( NPC->client )
02493 {
02494 NPC->client->saber[0].blade[7].color = TranslateSaberColor( value );
02495 }
02496 continue;
02497 }
02498
02499 if ( !Q_stricmp( token, "saber2Color" ) )
02500 {
02501 if ( COM_ParseString( &p, &value ) )
02502 {
02503 continue;
02504 }
02505 if ( NPC->client )
02506 {
02507 saber_colors_t color = TranslateSaberColor( value );
02508 for ( n = 0; n < MAX_BLADES; n++ )
02509 {
02510 NPC->client->saber[1].blade[n].color = color;
02511 }
02512 }
02513 continue;
02514 }
02515
02516 if ( !Q_stricmp( token, "saber2Color2" ) )
02517 {
02518 if ( COM_ParseString( &p, &value ) )
02519 {
02520 continue;
02521 }
02522 if ( NPC->client )
02523 {
02524 NPC->client->saber[1].blade[1].color = TranslateSaberColor( value );
02525 }
02526 continue;
02527 }
02528
02529 if ( !Q_stricmp( token, "saber2Color3" ) )
02530 {
02531 if ( COM_ParseString( &p, &value ) )
02532 {
02533 continue;
02534 }
02535 if ( NPC->client )
02536 {
02537 NPC->client->saber[1].blade[2].color = TranslateSaberColor( value );
02538 }
02539 continue;
02540 }
02541
02542 if ( !Q_stricmp( token, "saber2Color4" ) )
02543 {
02544 if ( COM_ParseString( &p, &value ) )
02545 {
02546 continue;
02547 }
02548 if ( NPC->client )
02549 {
02550 NPC->client->saber[1].blade[3].color = TranslateSaberColor( value );
02551 }
02552 continue;
02553 }
02554
02555 if ( !Q_stricmp( token, "saber2Color5" ) )
02556 {
02557 if ( COM_ParseString( &p, &value ) )
02558 {
02559 continue;
02560 }
02561 if ( NPC->client )
02562 {
02563 NPC->client->saber[1].blade[4].color = TranslateSaberColor( value );
02564 }
02565 continue;
02566 }
02567
02568 if ( !Q_stricmp( token, "saber2Color6" ) )
02569 {
02570 if ( COM_ParseString( &p, &value ) )
02571 {
02572 continue;
02573 }
02574 if ( NPC->client )
02575 {
02576 NPC->client->saber[1].blade[5].color = TranslateSaberColor( value );
02577 }
02578 continue;
02579 }
02580
02581 if ( !Q_stricmp( token, "saber2Color7" ) )
02582 {
02583 if ( COM_ParseString( &p, &value ) )
02584 {
02585 continue;
02586 }
02587 if ( NPC->client )
02588 {
02589 NPC->client->saber[1].blade[6].color = TranslateSaberColor( value );
02590 }
02591 continue;
02592 }
02593
02594 if ( !Q_stricmp( token, "saber2Color8" ) )
02595 {
02596 if ( COM_ParseString( &p, &value ) )
02597 {
02598 continue;
02599 }
02600 if ( NPC->client )
02601 {
02602 NPC->client->saber[1].blade[7].color = TranslateSaberColor( value );
02603 }
02604 continue;
02605 }
02606
02607
02608 if ( !Q_stricmp( token, "saberLength" ) )
02609 {
02610 if ( COM_ParseFloat( &p, &f ) )
02611 {
02612 SkipRestOfLine( &p );
02613 continue;
02614 }
02615
02616 if ( f < 4.0f )
02617 {
02618 f = 4.0f;
02619 }
02620
02621 for ( n = 0; n < MAX_BLADES; n++ )
02622 {
02623 NPC->client->saber[0].blade[n].lengthMax = f;
02624 }
02625 continue;
02626 }
02627
02628 if ( !Q_stricmp( token, "saberLength2" ) )
02629 {
02630 if ( COM_ParseFloat( &p, &f ) )
02631 {
02632 SkipRestOfLine( &p );
02633 continue;
02634 }
02635
02636 if ( f < 4.0f )
02637 {
02638 f = 4.0f;
02639 }
02640 NPC->client->saber[0].blade[1].lengthMax = f;
02641 continue;
02642 }
02643
02644 if ( !Q_stricmp( token, "saberLength3" ) )
02645 {
02646 if ( COM_ParseFloat( &p, &f ) )
02647 {
02648 SkipRestOfLine( &p );
02649 continue;
02650 }
02651
02652 if ( f < 4.0f )
02653 {
02654 f = 4.0f;
02655 }
02656 NPC->client->saber[0].blade[2].lengthMax = f;
02657 continue;
02658 }
02659
02660 if ( !Q_stricmp( token, "saberLength4" ) )
02661 {
02662 if ( COM_ParseFloat( &p, &f ) )
02663 {
02664 SkipRestOfLine( &p );
02665 continue;
02666 }
02667
02668 if ( f < 4.0f )
02669 {
02670 f = 4.0f;
02671 }
02672 NPC->client->saber[0].blade[3].lengthMax = f;
02673 continue;
02674 }
02675
02676 if ( !Q_stricmp( token, "saberLength5" ) )
02677 {
02678 if ( COM_ParseFloat( &p, &f ) )
02679 {
02680 SkipRestOfLine( &p );
02681 continue;
02682 }
02683
02684 if ( f < 4.0f )
02685 {
02686 f = 4.0f;
02687 }
02688 NPC->client->saber[0].blade[4].lengthMax = f;
02689 continue;
02690 }
02691
02692 if ( !Q_stricmp( token, "saberLength6" ) )
02693 {
02694 if ( COM_ParseFloat( &p, &f ) )
02695 {
02696 SkipRestOfLine( &p );
02697 continue;
02698 }
02699
02700 if ( f < 4.0f )
02701 {
02702 f = 4.0f;
02703 }
02704 NPC->client->saber[0].blade[5].lengthMax = f;
02705 continue;
02706 }
02707
02708 if ( !Q_stricmp( token, "saberLength7" ) )
02709 {
02710 if ( COM_ParseFloat( &p, &f ) )
02711 {
02712 SkipRestOfLine( &p );
02713 continue;
02714 }
02715
02716 if ( f < 4.0f )
02717 {
02718 f = 4.0f;
02719 }
02720 NPC->client->saber[0].blade[6].lengthMax = f;
02721 continue;
02722 }
02723
02724 if ( !Q_stricmp( token, "saberLength8" ) )
02725 {
02726 if ( COM_ParseFloat( &p, &f ) )
02727 {
02728 SkipRestOfLine( &p );
02729 continue;
02730 }
02731
02732 if ( f < 4.0f )
02733 {
02734 f = 4.0f;
02735 }
02736 NPC->client->saber[0].blade[7].lengthMax = f;
02737 continue;
02738 }
02739
02740 if ( !Q_stricmp( token, "saber2Length" ) )
02741 {
02742 if ( COM_ParseFloat( &p, &f ) )
02743 {
02744 SkipRestOfLine( &p );
02745 continue;
02746 }
02747
02748 if ( f < 4.0f )
02749 {
02750 f = 4.0f;
02751 }
02752 for ( n = 0; n < MAX_BLADES; n++ )
02753 {
02754 NPC->client->saber[1].blade[n].lengthMax = f;
02755 }
02756 continue;
02757 }
02758
02759 if ( !Q_stricmp( token, "saber2Length2" ) )
02760 {
02761 if ( COM_ParseFloat( &p, &f ) )
02762 {
02763 SkipRestOfLine( &p );
02764 continue;
02765 }
02766
02767 if ( f < 4.0f )
02768 {
02769 f = 4.0f;
02770 }
02771 NPC->client->saber[1].blade[1].lengthMax = f;
02772 continue;
02773 }
02774
02775 if ( !Q_stricmp( token, "saber2Length3" ) )
02776 {
02777 if ( COM_ParseFloat( &p, &f ) )
02778 {
02779 SkipRestOfLine( &p );
02780 continue;
02781 }
02782
02783 if ( f < 4.0f )
02784 {
02785 f = 4.0f;
02786 }
02787 NPC->client->saber[1].blade[2].lengthMax = f;
02788 continue;
02789 }
02790
02791 if ( !Q_stricmp( token, "saber2Length4" ) )
02792 {
02793 if ( COM_ParseFloat( &p, &f ) )
02794 {
02795 SkipRestOfLine( &p );
02796 continue;
02797 }
02798
02799 if ( f < 4.0f )
02800 {
02801 f = 4.0f;
02802 }
02803 NPC->client->saber[1].blade[3].lengthMax = f;
02804 continue;
02805 }
02806
02807 if ( !Q_stricmp( token, "saber2Length5" ) )
02808 {
02809 if ( COM_ParseFloat( &p, &f ) )
02810 {
02811 SkipRestOfLine( &p );
02812 continue;
02813 }
02814
02815 if ( f < 4.0f )
02816 {
02817 f = 4.0f;
02818 }
02819 NPC->client->saber[1].blade[4].lengthMax = f;
02820 continue;
02821 }
02822
02823 if ( !Q_stricmp( token, "saber2Length6" ) )
02824 {
02825 if ( COM_ParseFloat( &p, &f ) )
02826 {
02827 SkipRestOfLine( &p );
02828 continue;
02829 }
02830
02831 if ( f < 4.0f )
02832 {
02833 f = 4.0f;
02834 }
02835 NPC->client->saber[1].blade[5].lengthMax = f;
02836 continue;
02837 }
02838
02839 if ( !Q_stricmp( token, "saber2Length7" ) )
02840 {
02841 if ( COM_ParseFloat( &p, &f ) )
02842 {
02843 SkipRestOfLine( &p );
02844 continue;
02845 }
02846
02847 if ( f < 4.0f )
02848 {
02849 f = 4.0f;
02850 }
02851 NPC->client->saber[1].blade[6].lengthMax = f;
02852 continue;
02853 }
02854
02855 if ( !Q_stricmp( token, "saber2Length8" ) )
02856 {
02857 if ( COM_ParseFloat( &p, &f ) )
02858 {
02859 SkipRestOfLine( &p );
02860 continue;
02861 }
02862
02863 if ( f < 4.0f )
02864 {
02865 f = 4.0f;
02866 }
02867 NPC->client->saber[1].blade[7].lengthMax = f;
02868 continue;
02869 }
02870
02871
02872 if ( !Q_stricmp( token, "saberRadius" ) )
02873 {
02874 if ( COM_ParseFloat( &p, &f ) )
02875 {
02876 SkipRestOfLine( &p );
02877 continue;
02878 }
02879
02880 if ( f < 0.25f )
02881 {
02882 f = 0.25f;
02883 }
02884 for ( n = 0; n < MAX_BLADES; n++ )
02885 {
02886 NPC->client->saber[0].blade[n].radius = f;
02887 }
02888 continue;
02889 }
02890
02891 if ( !Q_stricmp( token, "saberRadius2" ) )
02892 {
02893 if ( COM_ParseFloat( &p, &f ) )
02894 {
02895 SkipRestOfLine( &p );
02896 continue;
02897 }
02898
02899 if ( f < 0.25f )
02900 {
02901 f = 0.25f;
02902 }
02903 NPC->client->saber[0].blade[1].radius = f;
02904 continue;
02905 }
02906
02907 if ( !Q_stricmp( token, "saberRadius3" ) )
02908 {
02909 if ( COM_ParseFloat( &p, &f ) )
02910 {
02911 SkipRestOfLine( &p );
02912 continue;
02913 }
02914
02915 if ( f < 0.25f )
02916 {
02917 f = 0.25f;
02918 }
02919 NPC->client->saber[0].blade[2].radius = f;
02920 continue;
02921 }
02922
02923 if ( !Q_stricmp( token, "saberRadius4" ) )
02924 {
02925 if ( COM_ParseFloat( &p, &f ) )
02926 {
02927 SkipRestOfLine( &p );
02928 continue;
02929 }
02930
02931 if ( f < 0.25f )
02932 {
02933 f = 0.25f;
02934 }
02935 NPC->client->saber[0].blade[3].radius = f;
02936 continue;
02937 }
02938
02939 if ( !Q_stricmp( token, "saberRadius5" ) )
02940 {
02941 if ( COM_ParseFloat( &p, &f ) )
02942 {
02943 SkipRestOfLine( &p );
02944 continue;
02945 }
02946
02947 if ( f < 0.25f )
02948 {
02949 f = 0.25f;
02950 }
02951 NPC->client->saber[0].blade[4].radius = f;
02952 continue;
02953 }
02954
02955 if ( !Q_stricmp( token, "saberRadius6" ) )
02956 {
02957 if ( COM_ParseFloat( &p, &f ) )
02958 {
02959 SkipRestOfLine( &p );
02960 continue;
02961 }
02962
02963 if ( f < 0.25f )
02964 {
02965 f = 0.25f;
02966 }
02967 NPC->client->saber[0].blade[5].radius = f;
02968 continue;
02969 }
02970
02971 if ( !Q_stricmp( token, "saberRadius7" ) )
02972 {
02973 if ( COM_ParseFloat( &p, &f ) )
02974 {
02975 SkipRestOfLine( &p );
02976 continue;
02977 }
02978
02979 if ( f < 0.25f )
02980 {
02981 f = 0.25f;
02982 }
02983 NPC->client->saber[0].blade[6].radius = f;
02984 continue;
02985 }
02986
02987 if ( !Q_stricmp( token, "saberRadius8" ) )
02988 {
02989 if ( COM_ParseFloat( &p, &f ) )
02990 {
02991 SkipRestOfLine( &p );
02992 continue;
02993 }
02994
02995 if ( f < 0.25f )
02996 {
02997 f = 0.25f;
02998 }
02999 NPC->client->saber[0].blade[7].radius = f;
03000 continue;
03001 }
03002
03003 if ( !Q_stricmp( token, "saber2Radius" ) )
03004 {
03005 if ( COM_ParseFloat( &p, &f ) )
03006 {
03007 SkipRestOfLine( &p );
03008 continue;
03009 }
03010
03011 if ( f < 0.25f )
03012 {
03013 f = 0.25f;
03014 }
03015 for ( n = 0; n < MAX_BLADES; n++ )
03016 {
03017 NPC->client->saber[1].blade[n].radius = f;
03018 }
03019 continue;
03020 }
03021
03022 if ( !Q_stricmp( token, "saber2Radius2" ) )
03023 {
03024 if ( COM_ParseFloat( &p, &f ) )
03025 {
03026 SkipRestOfLine( &p );
03027 continue;
03028 }
03029
03030 if ( f < 0.25f )
03031 {
03032 f = 0.25f;
03033 }
03034 NPC->client->saber[1].blade[1].radius = f;
03035 continue;
03036 }
03037
03038 if ( !Q_stricmp( token, "saber2Radius3" ) )
03039 {
03040 if ( COM_ParseFloat( &p, &f ) )
03041 {
03042 SkipRestOfLine( &p );
03043 continue;
03044 }
03045
03046 if ( f < 0.25f )
03047 {
03048 f = 0.25f;
03049 }
03050 NPC->client->saber[1].blade[2].radius = f;
03051 continue;
03052 }
03053
03054 if ( !Q_stricmp( token, "saber2Radius4" ) )
03055 {
03056 if ( COM_ParseFloat( &p, &f ) )
03057 {
03058 SkipRestOfLine( &p );
03059 continue;
03060 }
03061
03062 if ( f < 0.25f )
03063 {
03064 f = 0.25f;
03065 }
03066 NPC->client->saber[1].blade[3].radius = f;
03067 continue;
03068 }
03069
03070 if ( !Q_stricmp( token, "saber2Radius5" ) )
03071 {
03072 if ( COM_ParseFloat( &p, &f ) )
03073 {
03074 SkipRestOfLine( &p );
03075 continue;
03076 }
03077
03078 if ( f < 0.25f )
03079 {
03080 f = 0.25f;
03081 }
03082 NPC->client->saber[1].blade[4].radius = f;
03083 continue;
03084 }
03085
03086 if ( !Q_stricmp( token, "saber2Radius6" ) )
03087 {
03088 if ( COM_ParseFloat( &p, &f ) )
03089 {
03090 SkipRestOfLine( &p );
03091 continue;
03092 }
03093
03094 if ( f < 0.25f )
03095 {
03096 f = 0.25f;
03097 }
03098 NPC->client->saber[1].blade[5].radius = f;
03099 continue;
03100 }
03101
03102 if ( !Q_stricmp( token, "saber2Radius7" ) )
03103 {
03104 if ( COM_ParseFloat( &p, &f ) )
03105 {
03106 SkipRestOfLine( &p );
03107 continue;
03108 }
03109
03110 if ( f < 0.25f )
03111 {
03112 f = 0.25f;
03113 }
03114 NPC->client->saber[1].blade[6].radius = f;
03115 continue;
03116 }
03117
03118 if ( !Q_stricmp( token, "saber2Radius8" ) )
03119 {
03120 if ( COM_ParseFloat( &p, &f ) )
03121 {
03122 SkipRestOfLine( &p );
03123 continue;
03124 }
03125
03126 if ( f < 0.25f )
03127 {
03128 f = 0.25f;
03129 }
03130 NPC->client->saber[1].blade[7].radius = f;
03131 continue;
03132 }
03133
03134
03135
03136
03137
03138
03139 if ( !Q_stricmp( token, "saberStyle" ) )
03140 {
03141 if ( COM_ParseInt( &p, &n ) )
03142 {
03143 SkipRestOfLine( &p );
03144 continue;
03145 }
03146
03147 if ( n < 0 )
03148 {
03149 n = 0;
03150 }
03151 else if ( n > 5 )
03152 {
03153 n = 5;
03154 }
03155 NPC->client->ps.fd.saberAnimLevel = n;
03156
03157
03158
03159
03160
03161
03162 continue;
03163 }
03164
03165 if ( !parsingPlayer )
03166 {
03167 Com_Printf( "WARNING: unknown keyword '%s' while parsing '%s'\n", token, NPCName );
03168 }
03169 SkipRestOfLine( &p );
03170 }
03171 }
03172
03173
03174
03175
03176 if ( !md3Model )
03177 {
03178 qboolean setTypeBack = qfalse;
03179
03180 if (npcSaber1 == 0)
03181 {
03182 npcSaber1 = G_ModelIndex("@Kyle");
03183 WP_SaberParseParms( "Kyle", &NPC->client->saber[0] );
03184 }
03185
03186 NPC->s.npcSaber1 = npcSaber1;
03187 NPC->s.npcSaber2 = npcSaber2;
03188
03189 if (!customSkin[0])
03190 {
03191 strcpy(customSkin, "default");
03192 }
03193
03194 if ( NPC->client && NPC->client->NPC_class == CLASS_VEHICLE )
03195 {
03196
03197 strcpy(playerModel, va("$%s", NPCName));
03198 }
03199 SetupGameGhoul2Model(NPC, playerModel, customSkin);
03200
03201 if (!NPC->NPC_type)
03202 {
03203 NPC->NPC_type = (char *)NPCName;
03204 setTypeBack = qtrue;
03205 }
03206
03207 NPC_Precache(NPC);
03208
03209 if (setTypeBack)
03210 {
03211 NPC->NPC_type = NULL;
03212 }
03213 }
03214 else
03215 {
03216 Com_Printf("MD3 MODEL NPC'S ARE NOT SUPPORTED IN MP!\n");
03217 return qfalse;
03218 }
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232 return qtrue;
03233 }
03234
03235 #ifdef _XBOX
03236 char *npcParseBuffer = NULL;
03237 #else
03238 char npcParseBuffer[MAX_NPC_DATA_SIZE];
03239 #endif
03240
03241 void NPC_LoadParms( void )
03242 {
03243 int len, totallen, npcExtFNLen, mainBlockLen, fileCnt, i;
03244
03245 char *holdChar, *marker;
03246 char npcExtensionListBuf[2048];
03247 fileHandle_t f;
03248 len = 0;
03249
03250
03251 totallen = mainBlockLen = len;
03252 marker = NPCParms+totallen;
03253 *marker = 0;
03254
03255
03256 fileCnt = trap_FS_GetFileList("ext_data/NPCs", ".npc", npcExtensionListBuf, sizeof(npcExtensionListBuf) );
03257
03258 #ifdef _XBOX
03259 npcParseBuffer = (char *) Z_Malloc(MAX_NPC_DATA_SIZE, TAG_TEMP_WORKSPACE, qfalse, 4);
03260 #endif
03261
03262 holdChar = npcExtensionListBuf;
03263 for ( i = 0; i < fileCnt; i++, holdChar += npcExtFNLen + 1 )
03264 {
03265 npcExtFNLen = strlen( holdChar );
03266
03267
03268
03269 len = trap_FS_FOpenFile(va( "ext_data/NPCs/%s", holdChar), &f, FS_READ);
03270
03271 if ( len == -1 )
03272 {
03273 Com_Printf( "error reading file\n" );
03274 }
03275 else
03276 {
03277 if ( totallen + len >= MAX_NPC_DATA_SIZE ) {
03278 G_Error( "NPC extensions (*.npc) are too large" );
03279 }
03280 trap_FS_Read(npcParseBuffer, len, f);
03281 npcParseBuffer[len] = 0;
03282
03283 len = COM_Compress( npcParseBuffer );
03284
03285 strcat( marker, npcParseBuffer );
03286 strcat(marker, "\n");
03287 len++;
03288 trap_FS_FCloseFile(f);
03289
03290 totallen += len;
03291 marker = NPCParms+totallen;
03292
03293
03294 }
03295 }
03296
03297 #ifdef _XBOX
03298 Z_Free(npcParseBuffer);
03299 npcParseBuffer = NULL;
03300 #endif
03301
03302 }