00001
00002
00003 #include "b_local.h"
00004 #include "anims.h"
00005 #include "w_saber.h"
00006 #include "bg_saga.h"
00007 #include "bg_vehicles.h"
00008 #include "g_nav.h"
00009
00010 extern void G_DebugPrint( int level, const char *format, ... );
00011
00012 extern qboolean G_CheckInSolid (gentity_t *self, qboolean fix);
00013 extern void ClientUserinfoChanged( int clientNum );
00014 extern qboolean SpotWouldTelefrag2( gentity_t *mover, vec3_t dest );
00015 extern void Jedi_Cloak( gentity_t *self );
00016
00017
00018
00019 extern void Q3_SetParm (int entID, int parmNum, const char *parmValue);
00020 extern team_t TranslateTeamName( const char *name );
00021 extern char *TeamNames[TEAM_NUM_TEAMS];
00022
00023
00024
00025
00026
00027 extern void PM_SetTorsoAnimTimer( gentity_t *ent, int *torsoAnimTimer, int time );
00028 extern void PM_SetLegsAnimTimer( gentity_t *ent, int *legsAnimTimer, int time );
00029
00030 extern void ST_ClearTimers( gentity_t *ent );
00031 extern void Jedi_ClearTimers( gentity_t *ent );
00032 extern void NPC_ShadowTrooper_Precache( void );
00033 extern void NPC_Gonk_Precache( void );
00034 extern void NPC_Mouse_Precache( void );
00035 extern void NPC_Seeker_Precache( void );
00036 extern void NPC_Remote_Precache( void );
00037 extern void NPC_R2D2_Precache(void);
00038 extern void NPC_R5D2_Precache(void);
00039 extern void NPC_Probe_Precache(void);
00040 extern void NPC_Interrogator_Precache(gentity_t *self);
00041 extern void NPC_MineMonster_Precache( void );
00042 extern void NPC_Howler_Precache( void );
00043 extern void NPC_ATST_Precache(void);
00044 extern void NPC_Sentry_Precache(void);
00045 extern void NPC_Mark1_Precache(void);
00046 extern void NPC_Mark2_Precache(void);
00047 extern void NPC_GalakMech_Precache( void );
00048 extern void NPC_GalakMech_Init( gentity_t *ent );
00049 extern void NPC_Protocol_Precache( void );
00050 extern void Boba_Precache( void );
00051 extern void NPC_Wampa_Precache( void );
00052 gentity_t *NPC_SpawnType( gentity_t *ent, char *npc_type, char *targetname, qboolean isVehicle );
00053
00054 extern void Rancor_SetBolts( gentity_t *self );
00055 extern void Wampa_SetBolts( gentity_t *self );
00056
00057 #define NSF_DROP_TO_FLOOR 16
00058
00059
00060
00061 extern void funcBBrushPain (gentity_t *self, gentity_t *attacker, int damage);
00062 extern void misc_model_breakable_pain (gentity_t *self, gentity_t *attacker, int damage);
00063 extern void NPC_Pain (gentity_t *self, gentity_t *attacker, int damage);
00064 extern void station_pain (gentity_t *self, gentity_t *attacker, int damage);
00065 extern void func_usable_pain (gentity_t *self, gentity_t *attacker, int damage);
00066 extern void NPC_ATST_Pain (gentity_t *self, gentity_t *attacker, int damage);
00067 extern void NPC_ST_Pain (gentity_t *self, gentity_t *attacker, int damage);
00068 extern void NPC_Jedi_Pain (gentity_t *self, gentity_t *attacker, int damage);
00069 extern void NPC_Droid_Pain (gentity_t *self, gentity_t *attacker, int damage);
00070 extern void NPC_Probe_Pain (gentity_t *self, gentity_t *attacker, int damage);
00071 extern void NPC_MineMonster_Pain (gentity_t *self, gentity_t *attacker, int damage);
00072 extern void NPC_Howler_Pain (gentity_t *self, gentity_t *attacker, int damage);
00073 extern void NPC_Seeker_Pain (gentity_t *self, gentity_t *attacker, int damage);
00074 extern void NPC_Remote_Pain (gentity_t *self, gentity_t *attacker, int damage);
00075 extern void emplaced_gun_pain (gentity_t *self, gentity_t *attacker, int damage);
00076 extern void NPC_Mark1_Pain (gentity_t *self, gentity_t *attacker, int damage);
00077 extern void NPC_GM_Pain (gentity_t *self, gentity_t *attacker, int damage);
00078 extern void NPC_Sentry_Pain (gentity_t *self, gentity_t *attacker, int damage);
00079 extern void NPC_Mark2_Pain (gentity_t *self, gentity_t *attacker, int damage);
00080 extern void PlayerPain (gentity_t *self, gentity_t *attacker, int damage);
00081 extern void GasBurst (gentity_t *self, gentity_t *attacker, int damage);
00082 extern void CrystalCratePain (gentity_t *self, gentity_t *attacker, int damage);
00083 extern void TurretPain (gentity_t *self, gentity_t *attacker, int damage);
00084 extern void NPC_Wampa_Pain (gentity_t *self, gentity_t *attacker, int damage);
00085 extern void NPC_Rancor_Pain (gentity_t *self, gentity_t *attacker, int damage);
00086
00087
00088
00089
00090 int WP_SetSaberModel( gclient_t *client, class_t npcClass )
00091 {
00092
00093 return 1;
00094 }
00095
00096
00097
00098
00099
00100
00101 typedef void (PAIN_FUNC) (gentity_t *self, gentity_t *attacker, int damage);
00102
00103 PAIN_FUNC *NPC_PainFunc( gentity_t *ent )
00104 {
00105 void (*func)(gentity_t *self, gentity_t *attacker, int damage);
00106
00107 if ( ent->client->ps.weapon == WP_SABER )
00108 {
00109 func = NPC_Jedi_Pain;
00110 }
00111 else
00112 {
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 switch( ent->client->NPC_class )
00123 {
00124
00125 case CLASS_STORMTROOPER:
00126 case CLASS_SWAMPTROOPER:
00127 func = NPC_ST_Pain;
00128 break;
00129
00130 case CLASS_SEEKER:
00131 func = NPC_Seeker_Pain;
00132 break;
00133
00134 case CLASS_REMOTE:
00135 func = NPC_Remote_Pain;
00136 break;
00137
00138 case CLASS_MINEMONSTER:
00139 func = NPC_MineMonster_Pain;
00140 break;
00141
00142 case CLASS_HOWLER:
00143 func = NPC_Howler_Pain;
00144 break;
00145
00146
00147 case CLASS_GONK:
00148 case CLASS_R2D2:
00149 case CLASS_R5D2:
00150 case CLASS_MOUSE:
00151 case CLASS_PROTOCOL:
00152 case CLASS_INTERROGATOR:
00153 func = NPC_Droid_Pain;
00154 break;
00155 case CLASS_PROBE:
00156 func = NPC_Probe_Pain;
00157 break;
00158
00159 case CLASS_SENTRY:
00160 func = NPC_Sentry_Pain;
00161 break;
00162 case CLASS_MARK1:
00163 func = NPC_Mark1_Pain;
00164 break;
00165 case CLASS_MARK2:
00166 func = NPC_Mark2_Pain;
00167 break;
00168 case CLASS_ATST:
00169 func = NPC_ATST_Pain;
00170 break;
00171 case CLASS_GALAKMECH:
00172 func = NPC_GM_Pain;
00173 break;
00174 case CLASS_RANCOR:
00175 func = NPC_Rancor_Pain;
00176 break;
00177 case CLASS_WAMPA:
00178 func = NPC_Wampa_Pain;
00179 break;
00180
00181 default:
00182 func = NPC_Pain;
00183 break;
00184 }
00185
00186 }
00187
00188 return func;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 typedef void (TOUCH_FUNC) (gentity_t *self, gentity_t *other, trace_t *trace);
00198
00199 TOUCH_FUNC *NPC_TouchFunc( gentity_t *ent )
00200 {
00201 void (*func)(gentity_t *self, gentity_t *other, trace_t *trace);
00202
00203 func = NPC_Touch;
00204
00205 return func;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214 extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponModel, int boltNum, int weaponNum );
00215 void NPC_SetMiscDefaultData( gentity_t *ent )
00216 {
00217 if ( ent->spawnflags & SFB_CINEMATIC )
00218 {
00219 ent->NPC->behaviorState = BS_CINEMATIC;
00220 }
00221 if ( ent->client->NPC_class == CLASS_BOBAFETT )
00222 {
00223 Boba_Precache();
00224 ent->client->ps.fd.forcePowersKnown |= ( 1 << FP_LEVITATION );
00225 ent->client->ps.fd.forcePowerLevel[FP_LEVITATION] = FORCE_LEVEL_3;
00226 ent->client->ps.fd.forcePower = 100;
00227 ent->NPC->scriptFlags |= (SCF_ALT_FIRE|SCF_NO_GROUPS);
00228 }
00229
00230 if (ent->s.NPC_class == CLASS_VEHICLE && ent->m_pVehicle)
00231 {
00232 ent->s.g2radius = 255;
00233
00234 if (ent->m_pVehicle->m_pVehicleInfo->type == VH_WALKER)
00235 {
00236 ent->mass = 2000;
00237 ent->flags |= (FL_SHIELDED|FL_NO_KNOCKBACK);
00238 ent->pain = NPC_ATST_Pain;
00239 }
00240
00241 trap_G2API_SetSurfaceOnOff( ent->ghoul2, "head_hatchcover", 0 );
00242 }
00243 if ( !Q_stricmp( "wampa", ent->NPC_type ) )
00244 {
00245 Wampa_SetBolts( ent );
00246 ent->s.g2radius = 80;
00247 ent->mass = 300;
00248 ent->flags |= FL_NO_KNOCKBACK;
00249 ent->pain = NPC_Wampa_Pain;
00250 }
00251 if ( ent->client->NPC_class == CLASS_RANCOR )
00252 {
00253 Rancor_SetBolts( ent );
00254 ent->s.g2radius = 255;
00255 ent->mass = 1000;
00256 ent->flags |= FL_NO_KNOCKBACK;
00257 ent->pain = NPC_Rancor_Pain;
00258 ent->health *= 4;
00259 }
00260 if ( !Q_stricmp( "Yoda", ent->NPC_type ) )
00261 {
00262 ent->NPC->scriptFlags |= SCF_NO_FORCE;
00263 }
00264 if ( !Q_stricmp( "emperor", ent->NPC_type ) )
00265 {
00266 ent->NPC->scriptFlags |= SCF_DONT_FIRE;
00267 }
00268
00269
00270 if (ent->client->ps.weapon == WP_SABER)
00271 {
00272
00273
00274 WP_SaberInitBladeData( ent );
00275 ent->client->ps.saberHolstered = 2;
00276
00277
00278
00279
00280
00281 Jedi_ClearTimers( ent );
00282 }
00283 if ( ent->client->ps.fd.forcePowersKnown != 0 )
00284 {
00285 WP_InitForcePowers( ent );
00286 WP_SpawnInitForcePowers(ent);
00287 }
00288 if ( ent->client->NPC_class == CLASS_SEEKER )
00289 {
00290 ent->NPC->defaultBehavior = BS_DEFAULT;
00291 ent->client->ps.gravity = 0;
00292 ent->NPC->aiFlags |= NPCAI_CUSTOM_GRAVITY;
00293 ent->client->ps.eFlags2 |= EF2_FLYING;
00294 ent->count = 30;
00295 }
00296
00297 switch(ent->client->playerTeam)
00298 {
00299 case NPCTEAM_PLAYER:
00300
00301 if ( ent->client->NPC_class == CLASS_JEDI || ent->client->NPC_class == CLASS_LUKE )
00302 {
00303 ent->client->enemyTeam = NPCTEAM_ENEMY;
00304 if ( ent->spawnflags & JSF_AMBUSH )
00305 {
00306 ent->NPC->scriptFlags |= SCF_IGNORE_ALERTS;
00307 ent->client->noclip = qtrue;
00308 }
00309 }
00310 else
00311 {
00312
00313
00314
00315
00316
00317
00318 switch ( ent->client->ps.weapon )
00319 {
00320 case WP_BRYAR_PISTOL:
00321
00322 case WP_DISRUPTOR:
00323 case WP_BOWCASTER:
00324 case WP_REPEATER:
00325 case WP_DEMP2:
00326 case WP_FLECHETTE:
00327 case WP_ROCKET_LAUNCHER:
00328 default:
00329 break;
00330 case WP_THERMAL:
00331 case WP_BLASTER:
00332
00333
00334
00335 ST_ClearTimers( ent );
00336 if ( ent->NPC->rank >= RANK_LT || ent->client->ps.weapon == WP_THERMAL )
00337 {
00338
00339
00340 }
00341 break;
00342 }
00343 }
00344 if ( ent->client->NPC_class == CLASS_KYLE || ent->client->NPC_class == CLASS_VEHICLE || (ent->spawnflags & SFB_CINEMATIC) )
00345 {
00346 ent->NPC->defaultBehavior = BS_CINEMATIC;
00347 }
00348 else
00349 {
00350
00351
00352
00353
00354 }
00355 break;
00356
00357 case NPCTEAM_NEUTRAL:
00358
00359 if ( Q_stricmp( ent->NPC_type, "gonk" ) == 0 )
00360 {
00361
00362 ent->r.svFlags |= SVF_PLAYER_USABLE;
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 }
00381 break;
00382
00383 case NPCTEAM_ENEMY:
00384 {
00385 ent->NPC->defaultBehavior = BS_DEFAULT;
00386 if ( ent->client->NPC_class == CLASS_SHADOWTROOPER )
00387 {
00388 Jedi_Cloak( ent );
00389 }
00390 if( ent->client->NPC_class == CLASS_TAVION ||
00391 ent->client->NPC_class == CLASS_REBORN ||
00392 ent->client->NPC_class == CLASS_DESANN ||
00393 ent->client->NPC_class == CLASS_SHADOWTROOPER )
00394 {
00395 ent->client->enemyTeam = NPCTEAM_PLAYER;
00396 if ( ent->spawnflags & JSF_AMBUSH )
00397 {
00398 ent->NPC->scriptFlags |= SCF_IGNORE_ALERTS;
00399 ent->client->noclip = qtrue;
00400 }
00401 }
00402 else if( ent->client->NPC_class == CLASS_PROBE || ent->client->NPC_class == CLASS_REMOTE ||
00403 ent->client->NPC_class == CLASS_INTERROGATOR || ent->client->NPC_class == CLASS_SENTRY)
00404 {
00405 ent->NPC->defaultBehavior = BS_DEFAULT;
00406 ent->client->ps.gravity = 0;
00407 ent->NPC->aiFlags |= NPCAI_CUSTOM_GRAVITY;
00408 ent->client->ps.eFlags2 |= EF2_FLYING;
00409 }
00410 else
00411 {
00412
00413 switch ( ent->client->ps.weapon )
00414 {
00415 case WP_BRYAR_PISTOL:
00416 break;
00417
00418
00419 case WP_DISRUPTOR:
00420
00421
00422 break;
00423 case WP_BOWCASTER:
00424 break;
00425 case WP_REPEATER:
00426
00427 break;
00428 case WP_DEMP2:
00429 break;
00430 case WP_FLECHETTE:
00431
00432 if ( !Q_stricmp( "stofficeralt", ent->NPC_type ) )
00433 {
00434
00435 }
00436 break;
00437 case WP_ROCKET_LAUNCHER:
00438 break;
00439 case WP_THERMAL:
00440
00441
00442 break;
00443 case WP_STUN_BATON:
00444 break;
00445 default:
00446 case WP_BLASTER:
00447
00448
00449 ST_ClearTimers( ent );
00450 if ( ent->NPC->rank >= RANK_COMMANDER )
00451 {
00452
00453 }
00454 if ( !Q_stricmp( "rodian2", ent->NPC_type ) )
00455 {
00456
00457 }
00458 break;
00459 }
00460 if ( !Q_stricmp( "galak_mech", ent->NPC_type ) )
00461 {
00462 NPC_GalakMech_Init( ent );
00463 }
00464 }
00465 }
00466 break;
00467
00468 default:
00469 break;
00470 }
00471
00472
00473 if ( ent->client->NPC_class == CLASS_SEEKER
00474 && ent->activator )
00475 {
00476 }
00477 else
00478 {
00479
00480 if (g_gametype.integer == GT_SIEGE && ent->s.NPC_class != CLASS_VEHICLE)
00481 {
00482 if (ent->client->enemyTeam == NPCTEAM_PLAYER)
00483 {
00484 ent->client->sess.sessionTeam = SIEGETEAM_TEAM1;
00485 }
00486 else if (ent->client->enemyTeam == NPCTEAM_ENEMY)
00487 {
00488 ent->client->sess.sessionTeam = SIEGETEAM_TEAM2;
00489 }
00490 else
00491 {
00492 ent->client->sess.sessionTeam = TEAM_FREE;
00493 }
00494 }
00495 }
00496
00497 if ( ent->client->NPC_class == CLASS_ATST || ent->client->NPC_class == CLASS_MARK1 )
00498 {
00499 ent->flags |= (FL_SHIELDED|FL_NO_KNOCKBACK);
00500 }
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 int NPC_WeaponsForTeam( team_t team, int spawnflags, const char *NPC_type )
00510 {
00511
00512 switch(team)
00513 {
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 case NPCTEAM_ENEMY:
00529 if ( Q_stricmp( "tavion", NPC_type ) == 0 ||
00530 Q_strncmp( "reborn", NPC_type, 6 ) == 0 ||
00531 Q_stricmp( "desann", NPC_type ) == 0 ||
00532 Q_strncmp( "shadowtrooper", NPC_type, 13 ) == 0 )
00533 return ( 1 << WP_SABER);
00534
00535
00536
00537
00538
00539
00540 if ( Q_strncmp( "stofficer", NPC_type, 9 ) == 0 )
00541 {
00542 return ( 1 << WP_FLECHETTE);
00543 }
00544 if ( Q_stricmp( "stcommander", NPC_type ) == 0 )
00545 {
00546 return ( 1 << WP_REPEATER);
00547 }
00548 if ( Q_stricmp( "swamptrooper", NPC_type ) == 0 )
00549 {
00550 return ( 1 << WP_FLECHETTE);
00551 }
00552 if ( Q_stricmp( "swamptrooper2", NPC_type ) == 0 )
00553 {
00554 return ( 1 << WP_REPEATER);
00555 }
00556 if ( Q_stricmp( "rockettrooper", NPC_type ) == 0 )
00557 {
00558 return ( 1 << WP_ROCKET_LAUNCHER);
00559 }
00560 if ( Q_strncmp( "shadowtrooper", NPC_type, 13 ) == 0 )
00561 {
00562 return ( 1 << WP_SABER);
00563 }
00564 if ( Q_stricmp( "imperial", NPC_type ) == 0 )
00565 {
00566
00567 return ( 1 << WP_BLASTER);
00568 }
00569 if ( Q_strncmp( "impworker", NPC_type, 9 ) == 0 )
00570 {
00571
00572 return ( 1 << WP_BLASTER);
00573 }
00574 if ( Q_stricmp( "stormpilot", NPC_type ) == 0 )
00575 {
00576
00577 return ( 1 << WP_BLASTER);
00578 }
00579 if ( Q_stricmp( "galak", NPC_type ) == 0 )
00580 {
00581 return ( 1 << WP_BLASTER);
00582 }
00583 if ( Q_stricmp( "galak_mech", NPC_type ) == 0 )
00584 {
00585 return ( 1 << WP_REPEATER);
00586 }
00587 if ( Q_strncmp( "ugnaught", NPC_type, 8 ) == 0 )
00588 {
00589 return WP_NONE;
00590 }
00591 if ( Q_stricmp( "granshooter", NPC_type ) == 0 )
00592 {
00593 return ( 1 << WP_BLASTER);
00594 }
00595 if ( Q_stricmp( "granboxer", NPC_type ) == 0 )
00596 {
00597 return ( 1 << WP_STUN_BATON);
00598 }
00599 if ( Q_strncmp( "gran", NPC_type, 4 ) == 0 )
00600 {
00601 return (( 1 << WP_THERMAL)|( 1 << WP_STUN_BATON));
00602 }
00603 if ( Q_stricmp( "rodian", NPC_type ) == 0 )
00604 {
00605 return ( 1 << WP_DISRUPTOR);
00606 }
00607 if ( Q_stricmp( "rodian2", NPC_type ) == 0 )
00608 {
00609 return ( 1 << WP_BLASTER);
00610 }
00611
00612 if (( Q_stricmp( "interrogator",NPC_type) == 0) || ( Q_stricmp( "sentry",NPC_type) == 0) || (Q_strncmp( "protocol",NPC_type,8) == 0) )
00613 {
00614 return WP_NONE;
00615 }
00616
00617 if ( Q_strncmp( "weequay", NPC_type, 7 ) == 0 )
00618 {
00619 return ( 1 << WP_BOWCASTER);
00620 }
00621 if ( Q_stricmp( "impofficer", NPC_type ) == 0 )
00622 {
00623 return ( 1 << WP_BLASTER);
00624 }
00625 if ( Q_stricmp( "impcommander", NPC_type ) == 0 )
00626 {
00627 return ( 1 << WP_BLASTER);
00628 }
00629 if (( Q_stricmp( "probe", NPC_type ) == 0 ) || ( Q_stricmp( "seeker", NPC_type ) == 0 ))
00630 {
00631
00632 return 0;
00633 }
00634 if ( Q_stricmp( "remote", NPC_type ) == 0 )
00635 {
00636
00637 return 0;
00638 }
00639 if ( Q_stricmp( "trandoshan", NPC_type ) == 0 )
00640 {
00641 return (1<<WP_REPEATER);
00642 }
00643 if ( Q_stricmp( "atst", NPC_type ) == 0 )
00644 {
00645
00646 return 0;
00647 }
00648 if ( Q_stricmp( "mark1", NPC_type ) == 0 )
00649 {
00650
00651 return 0;
00652 }
00653 if ( Q_stricmp( "mark2", NPC_type ) == 0 )
00654 {
00655
00656 return 0;
00657 }
00658 if ( Q_stricmp( "minemonster", NPC_type ) == 0 )
00659 {
00660 return (( 1 << WP_STUN_BATON));
00661 }
00662 if ( Q_stricmp( "howler", NPC_type ) == 0 )
00663 {
00664 return (( 1 << WP_STUN_BATON));
00665 }
00666
00667 return ( 1 << WP_BLASTER);
00668 break;
00669
00670 case NPCTEAM_PLAYER:
00671
00672
00673
00674
00675 if(spawnflags & SFB_RIFLEMAN)
00676 return ( 1 << WP_REPEATER);
00677
00678 if(spawnflags & SFB_PHASER)
00679
00680 return ( 1 << WP_BLASTER);
00681
00682 if ( Q_strncmp( "jedi", NPC_type, 4 ) == 0 || Q_stricmp( "luke", NPC_type ) == 0 )
00683 return ( 1 << WP_SABER);
00684
00685 if ( Q_strncmp( "prisoner", NPC_type, 8 ) == 0 )
00686 {
00687 return WP_NONE;
00688 }
00689 if ( Q_strncmp( "bespincop", NPC_type, 9 ) == 0 )
00690 {
00691
00692 return ( 1 << WP_BLASTER);
00693 }
00694
00695 if ( Q_stricmp( "MonMothma", NPC_type ) == 0 )
00696 {
00697 return WP_NONE;
00698 }
00699
00700
00701 return ( 1 << WP_BLASTER);
00702 break;
00703
00704 case NPCTEAM_NEUTRAL:
00705
00706 if ( Q_stricmp( "mark1", NPC_type ) == 0 )
00707 {
00708 return WP_NONE;
00709 }
00710 if ( Q_stricmp( "mark2", NPC_type ) == 0 )
00711 {
00712 return WP_NONE;
00713 }
00714 if ( Q_strncmp( "ugnaught", NPC_type, 8 ) == 0 )
00715 {
00716 return WP_NONE;
00717 }
00718 if ( Q_stricmp( "bartender", NPC_type ) == 0 )
00719 {
00720 return WP_NONE;
00721 }
00722 if ( Q_stricmp( "morgankatarn", NPC_type ) == 0 )
00723 {
00724 return WP_NONE;
00725 }
00726
00727 break;
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 default:
00745 break;
00746 }
00747
00748 return WP_NONE;
00749 }
00750
00751 extern void ChangeWeapon( gentity_t *ent, int newWeapon );
00752
00753
00754
00755
00756
00757
00758
00759 void NPC_SetWeapons( gentity_t *ent )
00760 {
00761 int bestWeap = WP_NONE;
00762 int curWeap;
00763 int weapons = NPC_WeaponsForTeam( ent->client->playerTeam, ent->spawnflags, ent->NPC_type );
00764
00765 ent->client->ps.stats[STAT_WEAPONS] = 0;
00766 for ( curWeap = WP_SABER; curWeap < WP_NUM_WEAPONS; curWeap++ )
00767 {
00768 if ( (weapons & ( 1 << curWeap )) )
00769 {
00770 ent->client->ps.stats[STAT_WEAPONS] |= ( 1 << curWeap );
00771
00772
00773 ent->NPC->currentAmmo = ent->client->ps.ammo[weaponData[curWeap].ammoIndex] = 100;
00774
00775 if ( bestWeap == WP_SABER )
00776 {
00777
00778 continue;
00779 }
00780
00781 if ( curWeap == WP_STUN_BATON )
00782 {
00783 if ( bestWeap == WP_NONE )
00784 {
00785 bestWeap = curWeap;
00786 }
00787 }
00788 else if ( curWeap > bestWeap || bestWeap == WP_STUN_BATON )
00789 {
00790
00791 bestWeap = curWeap;
00792 }
00793 }
00794 }
00795
00796 ent->client->ps.weapon = bestWeap;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 void NPC_SpawnEffect (gentity_t *ent)
00809 {
00810 }
00811
00812
00813
00814
00815
00816
00817 void NPC_SetFX_SpawnStates( gentity_t *ent )
00818 {
00819 if ( !(ent->NPC->aiFlags&NPCAI_CUSTOM_GRAVITY) )
00820 {
00821 ent->client->ps.gravity = g_gravity.value;
00822 }
00823 }
00824
00825
00826
00827
00828
00829
00830
00831 qboolean NPC_SpotWouldTelefrag( gentity_t *npc )
00832 {
00833 int i, num;
00834 int touch[MAX_GENTITIES];
00835 gentity_t *hit;
00836 vec3_t mins, maxs;
00837
00838 VectorAdd( npc->r.currentOrigin, npc->r.mins, mins );
00839 VectorAdd( npc->r.currentOrigin, npc->r.maxs, maxs );
00840 num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
00841
00842 for (i=0 ; i<num ; i++)
00843 {
00844 hit = &g_entities[touch[i]];
00845
00846 if (hit->inuse
00847 && hit->client
00848 && hit->s.number != npc->s.number
00849 && (hit->r.contents&MASK_NPCSOLID)
00850 && hit->s.number != npc->r.ownerNum
00851 && hit->r.ownerNum != npc->s.number)
00852 {
00853 return qtrue;
00854 }
00855
00856 }
00857
00858 return qfalse;
00859 }
00860
00861
00862 void NPC_Begin (gentity_t *ent)
00863 {
00864 vec3_t spawn_origin, spawn_angles;
00865 gclient_t *client;
00866 usercmd_t ucmd;
00867 gentity_t *spawnPoint = NULL;
00868
00869 memset( &ucmd, 0, sizeof( ucmd ) );
00870
00871 if ( !(ent->spawnflags & SFB_NOTSOLID) )
00872 {
00873 if (NPC_SpotWouldTelefrag(ent))
00874 {
00875 if ( ent->wait < 0 )
00876 {
00877 G_DebugPrint( WL_DEBUG, "NPC %s could not spawn, firing target3 (%s) and removing self\n", ent->targetname, ent->target3 );
00878
00879 G_UseTargets2( ent, ent, ent->target3 );
00880
00881
00882 ent->think = G_FreeEntity;
00883 ent->nextthink = level.time + 100;
00884 }
00885 else
00886 {
00887 G_DebugPrint( WL_DEBUG, "NPC %s could not spawn, waiting %4.2 secs to try again\n", ent->targetname, ent->wait/1000.0f );
00888 ent->think = NPC_Begin;
00889 ent->nextthink = level.time + ent->wait;
00890 }
00891 return;
00892 }
00893 }
00894
00895 NPC_SpawnEffect( ent );
00896
00897 VectorCopy( ent->client->ps.origin, spawn_origin);
00898 VectorCopy( ent->s.angles, spawn_angles);
00899 spawn_angles[YAW] = ent->NPC->desiredYaw;
00900
00901 client = ent->client;
00902
00903
00904 client->ps.persistant[PERS_SPAWN_COUNT]++;
00905
00906 client->airOutTime = level.time + 12000;
00907
00908 client->ps.clientNum = ent->s.number;
00909
00910
00911 if ( ent->health )
00912 {
00913 client->pers.maxHealth = client->ps.stats[STAT_MAX_HEALTH] = ent->health;
00914 }
00915 else if ( ent->NPC->stats.health )
00916 {
00917
00918 if ( ent->client->NPC_class != CLASS_REBORN
00919 && ent->client->NPC_class != CLASS_SHADOWTROOPER
00920
00921
00922 && ent->client->NPC_class != CLASS_JEDI )
00923 {
00924 ent->NPC->stats.health += ent->NPC->stats.health/4 * g_spskill.integer;
00925 }
00926
00927 client->pers.maxHealth = client->ps.stats[STAT_MAX_HEALTH] = ent->NPC->stats.health;
00928 }
00929 else
00930 {
00931 client->pers.maxHealth = client->ps.stats[STAT_MAX_HEALTH] = 100;
00932 }
00933
00934 if ( !Q_stricmp( "rodian", ent->NPC_type ) )
00935 {
00936
00937 switch ( g_spskill.integer )
00938 {
00939 case 0:
00940 ent->NPC->stats.aim = 1;
00941 break;
00942 case 1:
00943 ent->NPC->stats.aim = Q_irand( 2, 3 );
00944 break;
00945 case 2:
00946 ent->NPC->stats.aim = Q_irand( 3, 4 );
00947 break;
00948 }
00949 }
00950 else if ( ent->client->NPC_class == CLASS_STORMTROOPER
00951 || ent->client->NPC_class == CLASS_SWAMPTROOPER
00952 || ent->client->NPC_class == CLASS_IMPWORKER
00953 || !Q_stricmp( "rodian2", ent->NPC_type ) )
00954 {
00955 switch ( g_spskill.integer )
00956 {
00957 case 0:
00958 ent->NPC->stats.yawSpeed *= 0.75f;
00959 if ( ent->client->NPC_class == CLASS_IMPWORKER )
00960 {
00961 ent->NPC->stats.aim -= Q_irand( 3, 6 );
00962 }
00963 break;
00964 case 1:
00965 if ( ent->client->NPC_class == CLASS_IMPWORKER )
00966 {
00967 ent->NPC->stats.aim -= Q_irand( 2, 4 );
00968 }
00969 break;
00970 case 2:
00971 ent->NPC->stats.yawSpeed *= 1.5f;
00972 if ( ent->client->NPC_class == CLASS_IMPWORKER )
00973 {
00974 ent->NPC->stats.aim -= Q_irand( 0, 2 );
00975 }
00976 break;
00977 }
00978 }
00979 else if ( ent->client->NPC_class == CLASS_REBORN
00980 || ent->client->NPC_class == CLASS_SHADOWTROOPER )
00981 {
00982 switch ( g_spskill.integer )
00983 {
00984 case 1:
00985 ent->NPC->stats.yawSpeed *= 1.25f;
00986 break;
00987 case 2:
00988 ent->NPC->stats.yawSpeed *= 1.5f;
00989 break;
00990 }
00991 }
00992
00993
00994 ent->s.groundEntityNum = ENTITYNUM_NONE;
00995 ent->mass = 10;
00996 ent->takedamage = qtrue;
00997 ent->inuse = qtrue;
00998 ent->classname = "NPC";
00999
01000
01001
01002
01003
01004 if(!(ent->spawnflags & SFB_NOTSOLID))
01005 {
01006 ent->r.contents = CONTENTS_BODY;
01007 ent->clipmask = MASK_NPCSOLID;
01008 }
01009 else
01010 {
01011 ent->r.contents = 0;
01012 ent->clipmask = MASK_NPCSOLID&~CONTENTS_BODY;
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022 ent->die = player_die;
01023 ent->waterlevel = 0;
01024 ent->watertype = 0;
01025 ent->client->ps.rocketLockIndex = ENTITYNUM_NONE;
01026 ent->client->ps.rocketLockTime = 0;
01027
01028
01029 if ( ent->client->NPC_class != CLASS_R2D2 &&
01030 ent->client->NPC_class != CLASS_R5D2 &&
01031 ent->client->NPC_class != CLASS_MOUSE &&
01032 ent->client->NPC_class != CLASS_GONK &&
01033 ent->client->NPC_class != CLASS_PROTOCOL )
01034 {
01035 ent->flags &= ~FL_NOTARGET;
01036 }
01037 ent->s.eFlags &= ~EF_NODRAW;
01038
01039 NPC_SetFX_SpawnStates( ent );
01040
01041
01042
01043
01044 if ( ent->client->ps.weapon == WP_NONE )
01045 {
01046 NPC_SetWeapons(ent);
01047 }
01048
01049 ent->NPC->currentAmmo = ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex];
01050 ent->client->ps.weaponstate = WEAPON_IDLE;
01051 ChangeWeapon( ent, ent->client->ps.weapon );
01052
01053 VectorCopy( spawn_origin, client->ps.origin );
01054
01055
01056 client->ps.pm_flags |= PMF_RESPAWNED;
01057
01058
01059
01060 ent->s.eType = ET_NPC;
01061
01062
01063 VectorCopy (spawn_origin, ent->s.origin);
01064
01065
01066 SetClientViewAngle( ent, spawn_angles );
01067 client->renderInfo.lookTarget = ENTITYNUM_NONE;
01068
01069 if(!(ent->spawnflags & 64))
01070 {
01071 G_KillBox( ent );
01072 trap_LinkEntity (ent);
01073 }
01074
01075
01076 client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
01077 client->ps.pm_time = 100;
01078
01079 client->respawnTime = level.time;
01080 client->inactivityTime = level.time + g_inactivity.value * 1000;
01081 client->latched_buttons = 0;
01082 if ( ent->s.m_iVehicleNum )
01083 {
01084 }
01085 else if ( client->NPC_class == CLASS_SEEKER && ent->activator != NULL )
01086 {
01087 ent->s.owner = ent->r.ownerNum = ent->activator->s.number;
01088 }
01089 else
01090 {
01091 ent->s.owner = ENTITYNUM_NONE;
01092 }
01093
01094
01095 if ( ent->client->NPC_class != CLASS_VEHICLE )
01096 {
01097 NPC_SetAnim( ent, SETANIM_BOTH, BOTH_STAND1, SETANIM_FLAG_NORMAL );
01098 }
01099
01100 if( spawnPoint )
01101 {
01102
01103 G_UseTargets( spawnPoint, ent );
01104 }
01105
01106
01107 trap_ICARUS_InitEnt( ent );
01108
01109
01110 SetNPCGlobals( ent );
01111
01112 ent->enemy = NULL;
01113 NPCInfo->timeOfDeath = 0;
01114 NPCInfo->shotTime = 0;
01115 NPC_ClearGoal();
01116 NPC_ChangeWeapon( ent->client->ps.weapon );
01117
01118
01119 ent->pain = NPC_PainFunc( ent );
01120 ent->touch = NPC_TouchFunc( ent );
01121
01122
01123 ent->client->ps.ping = ent->NPC->stats.reactions * 50;
01124
01125
01126
01127 if (ent->s.NPC_class != CLASS_VEHICLE || g_gametype.integer != GT_SIEGE)
01128 {
01129 ent->client->ps.persistant[PERS_TEAM] = ent->client->playerTeam;
01130 }
01131
01132 ent->use = NPC_Use;
01133 ent->think = NPC_Think;
01134 ent->nextthink = level.time + FRAMETIME + Q_irand(0, 100);
01135
01136 NPC_SetMiscDefaultData( ent );
01137 if ( ent->health <= 0 )
01138 {
01139
01140 ent->health = client->ps.stats[STAT_HEALTH] = ent->client->pers.maxHealth;
01141 }
01142 else
01143 {
01144 client->ps.stats[STAT_HEALTH] = ent->health;
01145 }
01146
01147 if (ent->s.shouldtarget)
01148 {
01149 ent->maxHealth = ent->health;
01150 G_ScaleNetHealth(ent);
01151 }
01152
01153 ChangeWeapon( ent, ent->client->ps.weapon );
01154
01155 if ( !(ent->spawnflags & SFB_STARTINSOLID) )
01156 {
01157 G_CheckInSolid( ent, qtrue );
01158 }
01159 VectorClear( ent->NPC->lastClearOrigin );
01160
01161
01162 if ( G_ActivateBehavior( ent, BSET_SPAWN ) )
01163 {
01164 trap_ICARUS_MaintainTaskManager(ent->s.number);
01165 }
01166
01167 VectorCopy( ent->r.currentOrigin, ent->client->renderInfo.eyePoint );
01168
01169
01170
01171 memset( &ucmd, 0, sizeof( ucmd ) );
01172
01173 VectorCopy(client->pers.cmd.angles, ucmd.angles);
01174
01175 ent->client->ps.groundEntityNum = ENTITYNUM_NONE;
01176
01177 if ( ent->NPC->aiFlags & NPCAI_MATCHPLAYERWEAPON )
01178 {
01179
01180
01181 }
01182
01183 ClientThink( ent->s.number, &ucmd );
01184
01185 trap_LinkEntity( ent );
01186
01187 if ( ent->client->playerTeam == NPCTEAM_ENEMY )
01188 {
01189 if ( !(ent->spawnflags&SFB_CINEMATIC) && ent->NPC->behaviorState != BS_CINEMATIC )
01190 {
01191 if ( g_entities[0].client )
01192 {
01193
01194
01195
01196 }
01197 }
01198 }
01199 ent->waypoint = ent->NPC->homeWp = WAYPOINT_NONE;
01200
01201 if ( ent->m_pVehicle )
01202 {
01203
01204 if ( ent->m_pVehicle->m_iDroidUnitTag != -1 )
01205 {
01206 char *droidNPCType = NULL;
01207 gentity_t *droidEnt = NULL;
01208 if ( ent->model2
01209 && ent->model2[0] )
01210 {
01211 droidNPCType = ent->model2;
01212 }
01213 else if ( ent->m_pVehicle->m_pVehicleInfo->droidNPC
01214 && ent->m_pVehicle->m_pVehicleInfo->droidNPC[0] )
01215 {
01216 droidNPCType = ent->m_pVehicle->m_pVehicleInfo->droidNPC;
01217 }
01218
01219 if ( droidNPCType != NULL )
01220 {
01221 if ( Q_stricmp( "random", droidNPCType ) == 0
01222 || Q_stricmp( "default", droidNPCType ) == 0 )
01223 {
01224 if ( Q_irand( 0, 1 ) )
01225 {
01226 droidNPCType = "r2d2";
01227 }
01228 else
01229 {
01230 droidNPCType = "r5d2";
01231 }
01232 }
01233 droidEnt = NPC_SpawnType( ent, droidNPCType, NULL, qfalse );
01234 if ( droidEnt != NULL )
01235 {
01236 if ( droidEnt->client )
01237 {
01238 droidEnt->client->ps.m_iVehicleNum =
01239 droidEnt->s.m_iVehicleNum =
01240
01241 droidEnt->s.owner =
01242 droidEnt->r.ownerNum = ent->s.number;
01243 ent->m_pVehicle->m_pDroidUnit = (bgEntity_t *)droidEnt;
01244
01245
01246
01247 VectorCopy( ent->r.currentOrigin, droidEnt->s.origin );
01248 VectorCopy( ent->r.currentOrigin, droidEnt->client->ps.origin );
01249 G_SetOrigin( droidEnt, droidEnt->s.origin );
01250 trap_LinkEntity( droidEnt );
01251 VectorCopy( ent->r.currentAngles, droidEnt->s.angles );
01252 G_SetAngles( droidEnt, droidEnt->s.angles );
01253 if ( droidEnt->NPC )
01254 {
01255 droidEnt->NPC->desiredYaw = droidEnt->s.angles[YAW];
01256 droidEnt->NPC->desiredPitch = droidEnt->s.angles[PITCH];
01257 }
01258 droidEnt->flags |= FL_UNDYING;
01259 }
01260 else
01261 {
01262 G_FreeEntity( droidEnt );
01263 }
01264 }
01265 }
01266 }
01267 }
01268 }
01269
01270 gNPC_t *gNPCPtrs[MAX_GENTITIES];
01271
01272 gNPC_t *New_NPC_t(int entNum)
01273 {
01274 gNPC_t *ptr;
01275
01276 if (!gNPCPtrs[entNum])
01277 {
01278 gNPCPtrs[entNum] = (gNPC_t *)BG_Alloc (sizeof(gNPC_t));
01279 }
01280
01281 ptr = gNPCPtrs[entNum];
01282
01283 if (ptr)
01284 {
01285
01286
01287 memset(ptr, 0, sizeof( *ptr ) );
01288 }
01289
01290 return ptr;
01291 }
01292
01293 #ifdef _XBOX
01294 void NPC_NPCPtrsClear(void)
01295 {
01296 for(int i=0; i<MAX_GENTITIES; i++) {
01297 gNPCPtrs[i] = NULL;
01298 }
01299 }
01300 #endif
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 void NPC_DefaultScriptFlags( gentity_t *ent )
01351 {
01352 if ( !ent || !ent->NPC )
01353 {
01354 return;
01355 }
01356
01357 ent->NPC->scriptFlags = (SCF_CHASE_ENEMIES|SCF_LOOK_FOR_ENEMIES);
01358 }
01359
01360
01361
01362
01363
01364 #include "../namespace_begin.h"
01365 extern void G_CreateAnimalNPC( Vehicle_t **pVeh, const char *strAnimalType );
01366 extern void G_CreateSpeederNPC( Vehicle_t **pVeh, const char *strType );
01367 extern void G_CreateWalkerNPC( Vehicle_t **pVeh, const char *strAnimalType );
01368 extern void G_CreateFighterNPC( Vehicle_t **pVeh, const char *strType );
01369 #include "../namespace_end.h"
01370
01371 gentity_t *NPC_Spawn_Do( gentity_t *ent )
01372 {
01373 gentity_t *newent = NULL;
01374 int index;
01375 vec3_t saveOrg;
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 if ( ent->spawnflags & NSF_DROP_TO_FLOOR )
01387 {
01388 trace_t tr;
01389 vec3_t bottom;
01390
01391 VectorCopy( ent->r.currentOrigin, saveOrg );
01392 VectorCopy( ent->r.currentOrigin, bottom );
01393 bottom[2] = MIN_WORLD_COORD;
01394 trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, bottom, ent->s.number, MASK_NPCSOLID );
01395 if ( !tr.allsolid && !tr.startsolid && tr.fraction < 1.0 )
01396 {
01397 G_SetOrigin( ent, tr.endpos );
01398 }
01399 }
01400
01401
01402 if( ent->count != -1 )
01403 {
01404 ent->count--;
01405
01406 if( ent->count <= 0 )
01407 {
01408 ent->use = 0;
01409
01410 }
01411 }
01412
01413 newent = G_Spawn();
01414
01415 if ( newent == NULL )
01416 {
01417 Com_Printf ( S_COLOR_RED"ERROR: NPC G_Spawn failed\n" );
01418 return NULL;
01419 }
01420
01421 newent->fullName = ent->fullName;
01422
01423 newent->NPC = New_NPC_t(newent->s.number);
01424 if ( newent->NPC == NULL )
01425 {
01426 Com_Printf ( S_COLOR_RED"ERROR: NPC G_Alloc NPC failed\n" );
01427 goto finish;
01428 return NULL;
01429 }
01430
01431
01432 G_CreateFakeClient(newent->s.number, &newent->client);
01433
01434 newent->NPC->tempGoal = G_Spawn();
01435
01436 if ( newent->NPC->tempGoal == NULL )
01437 {
01438 newent->NPC = NULL;
01439 goto finish;
01440 return NULL;
01441 }
01442
01443 newent->NPC->tempGoal->classname = "NPC_goal";
01444 newent->NPC->tempGoal->parent = newent;
01445 newent->NPC->tempGoal->r.svFlags |= SVF_NOCLIENT;
01446
01447 if ( newent->client == NULL )
01448 {
01449 Com_Printf ( S_COLOR_RED"ERROR: NPC BG_Alloc client failed\n" );
01450 goto finish;
01451 return NULL;
01452 }
01453
01454 memset ( newent->client, 0, sizeof(*newent->client) );
01455
01456
01457 newent->playerState = &newent->client->ps;
01458
01459
01460
01461 if ( ent->NPC_type == NULL )
01462 {
01463 ent->NPC_type = "random";
01464 }
01465 else
01466 {
01467 ent->NPC_type = Q_strlwr( G_NewString( ent->NPC_type ) );
01468 }
01469
01470 if ( ent->r.svFlags & SVF_NO_BASIC_SOUNDS )
01471 {
01472 newent->r.svFlags |= SVF_NO_BASIC_SOUNDS;
01473 }
01474 if ( ent->r.svFlags & SVF_NO_COMBAT_SOUNDS )
01475 {
01476 newent->r.svFlags |= SVF_NO_COMBAT_SOUNDS;
01477 }
01478 if ( ent->r.svFlags & SVF_NO_EXTRA_SOUNDS )
01479 {
01480 newent->r.svFlags |= SVF_NO_EXTRA_SOUNDS;
01481 }
01482
01483 if ( ent->message )
01484 {
01485 newent->message = ent->message;
01486 newent->flags |= FL_NO_KNOCKBACK;
01487 }
01488
01489
01490 if ( Q_stricmp( ent->classname, "NPC_Vehicle" ) == 0 )
01491 {
01492
01493 int iVehIndex = BG_VehicleGetIndex( ent->NPC_type );
01494
01495 if ( iVehIndex == VEHICLE_NONE )
01496 {
01497 G_FreeEntity( newent );
01498
01499 G_FreeEntity( ent );
01500 return NULL;
01501 }
01502
01503
01504
01505
01506 switch( g_vehicleInfo[iVehIndex].type )
01507 {
01508 case VH_ANIMAL:
01509
01510 G_CreateAnimalNPC( &newent->m_pVehicle, ent->NPC_type );
01511 break;
01512 case VH_SPEEDER:
01513
01514 G_CreateSpeederNPC( &newent->m_pVehicle, ent->NPC_type );
01515 break;
01516 case VH_FIGHTER:
01517
01518 G_CreateFighterNPC( &newent->m_pVehicle, ent->NPC_type );
01519 break;
01520 case VH_WALKER:
01521
01522 G_CreateWalkerNPC( &newent->m_pVehicle, ent->NPC_type );
01523 break;
01524
01525 default:
01526 Com_Printf ( S_COLOR_RED "ERROR: Couldn't spawn NPC %s\n", ent->NPC_type );
01527 G_FreeEntity( newent );
01528
01529 G_FreeEntity( ent );
01530 return NULL;
01531 }
01532
01533 assert(newent->m_pVehicle &&
01534 newent->m_pVehicle->m_pVehicleInfo &&
01535 newent->m_pVehicle->m_pVehicleInfo->Initialize);
01536
01537
01538 newent->m_pVehicle->m_vOrientation = &newent->client->ps.vehOrientation[0];
01539
01540
01541 newent->m_pVehicle->m_pParentEntity = (bgEntity_t *)newent;
01542 newent->m_pVehicle->m_pVehicleInfo->Initialize( newent->m_pVehicle );
01543
01544
01545 newent->m_pVehicle->m_pVehicleInfo->RegisterAssets( newent->m_pVehicle );
01546
01547 newent->client->NPC_class = CLASS_VEHICLE;
01548 if ( g_vehicleInfo[iVehIndex].type == VH_FIGHTER )
01549 {
01550 newent->flags |= (FL_NO_KNOCKBACK|FL_SHIELDED|FL_DMG_BY_HEAVY_WEAP_ONLY);
01551 }
01552
01553
01554 newent->m_pVehicle->m_vOrientation[YAW] = ent->s.angles[YAW];
01555 newent->m_pVehicle->m_vOrientation[PITCH] = newent->m_pVehicle->m_vOrientation[ROLL] = 0.0f;
01556 G_SetAngles( newent, newent->m_pVehicle->m_vOrientation );
01557 SetClientViewAngle( newent, newent->m_pVehicle->m_vOrientation );
01558
01559
01560
01561
01562
01563
01564 newent->fly_sound_debounce_time = ent->fly_sound_debounce_time;
01565
01566
01567 newent->damage = ent->damage;
01568
01569
01570 newent->speed = ent->speed;
01571
01572
01573 newent->healingclass = ent->healingclass;
01574 newent->healingsound = ent->healingsound;
01575 newent->healingrate = ent->healingrate;
01576 newent->model2 = ent->model2;
01577 }
01578 else
01579 {
01580 newent->client->ps.weapon = WP_NONE;
01581 }
01582
01583 VectorCopy(ent->s.origin, newent->s.origin);
01584 VectorCopy(ent->s.origin, newent->client->ps.origin);
01585 VectorCopy(ent->s.origin, newent->r.currentOrigin);
01586 G_SetOrigin(newent, ent->s.origin);
01587
01588 if ( !NPC_ParseParms( ent->NPC_type, newent ) )
01589 {
01590 Com_Printf ( S_COLOR_RED "ERROR: Couldn't spawn NPC %s\n", ent->NPC_type );
01591 G_FreeEntity( newent );
01592
01593 G_FreeEntity( ent );
01594 return NULL;
01595 }
01596
01597 if ( ent->NPC_type )
01598 {
01599 if ( !Q_stricmp( ent->NPC_type, "kyle" ) )
01600 {
01601 newent->NPC->aiFlags |= NPCAI_MATCHPLAYERWEAPON;
01602 }
01603 else if ( !Q_stricmp( ent->NPC_type, "test" ) )
01604 {
01605 int n;
01606 for ( n = 0; n < 1 ; n++)
01607 {
01608 if ( g_entities[n].s.eType != ET_NPC && g_entities[n].client)
01609 {
01610 VectorCopy(g_entities[n].s.origin, newent->s.origin);
01611 newent->client->playerTeam = newent->s.teamowner = g_entities[n].client->playerTeam;
01612 break;
01613 }
01614 }
01615 newent->NPC->defaultBehavior = newent->NPC->behaviorState = BS_WAIT;
01616 newent->classname = "NPC";
01617
01618 }
01619 }
01620
01621
01622 if ( !newent->health )
01623 {
01624 newent->health = ent->health;
01625 }
01626 newent->script_targetname = ent->NPC_targetname;
01627 newent->targetname = ent->NPC_targetname;
01628 newent->target = ent->NPC_target;
01629 newent->target2 = ent->target2;
01630 newent->target3 = ent->target3;
01631 newent->target4 = ent->target4;
01632 newent->wait = ent->wait;
01633
01634 for( index = BSET_FIRST; index < NUM_BSETS; index++)
01635 {
01636 if ( ent->behaviorSet[index] )
01637 {
01638 newent->behaviorSet[index] = ent->behaviorSet[index];
01639 }
01640 }
01641
01642 newent->classname = "NPC";
01643 newent->NPC_type = ent->NPC_type;
01644 trap_UnlinkEntity(newent);
01645
01646 VectorCopy(ent->s.angles, newent->s.angles);
01647 VectorCopy(ent->s.angles, newent->r.currentAngles);
01648 VectorCopy(ent->s.angles, newent->client->ps.viewangles);
01649 newent->NPC->desiredYaw =ent->s.angles[YAW];
01650
01651 trap_LinkEntity(newent);
01652 newent->spawnflags = ent->spawnflags;
01653
01654 if(ent->paintarget)
01655 {
01656 newent->paintarget = ent->paintarget;
01657 }
01658 if(ent->opentarget)
01659 {
01660 newent->opentarget = ent->opentarget;
01661 }
01662
01663
01664 newent->s.eType = ET_NPC;
01665
01666
01667 if ( ent->parms )
01668 {
01669 int parmNum;
01670
01671 for ( parmNum = 0; parmNum < MAX_PARMS; parmNum++ )
01672 {
01673 if ( ent->parms->parm[parmNum] && ent->parms->parm[parmNum][0] )
01674 {
01675 Q3_SetParm( newent->s.number, parmNum, ent->parms->parm[parmNum] );
01676 }
01677 }
01678 }
01679
01680
01681
01682 newent->s.pos.trType = TR_INTERPOLATE;
01683 newent->s.pos.trTime = level.time;
01684 VectorCopy( newent->r.currentOrigin, newent->s.pos.trBase );
01685 VectorClear( newent->s.pos.trDelta );
01686 newent->s.pos.trDuration = 0;
01687
01688 newent->s.apos.trType = TR_INTERPOLATE;
01689 newent->s.apos.trTime = level.time;
01690
01691
01692 VectorCopy( newent->s.angles, newent->s.apos.trBase );
01693
01694 VectorClear( newent->s.apos.trDelta );
01695 newent->s.apos.trDuration = 0;
01696
01697 newent->NPC->combatPoint = -1;
01698
01699 newent->flags |= FL_NOTARGET;
01700 newent->s.eFlags |= EF_NODRAW;
01701
01702 newent->think = NPC_Begin;
01703 newent->nextthink = level.time + FRAMETIME;
01704 NPC_DefaultScriptFlags( newent );
01705
01706
01707 newent->s.shouldtarget = ent->s.shouldtarget;
01708 newent->s.teamowner = ent->s.teamowner;
01709 newent->alliedTeam = ent->alliedTeam;
01710 newent->teamnodmg = ent->teamnodmg;
01711 if ( ent->team && ent->team[0] )
01712 {
01713 newent->client->sess.sessionTeam = atoi(ent->team);
01714 }
01715 else if ( newent->s.teamowner != TEAM_FREE )
01716 {
01717 newent->client->sess.sessionTeam = newent->s.teamowner;
01718 }
01719 else if ( newent->alliedTeam != TEAM_FREE )
01720 {
01721 newent->client->sess.sessionTeam = newent->alliedTeam;
01722 }
01723 else if ( newent->teamnodmg != TEAM_FREE )
01724 {
01725 newent->client->sess.sessionTeam = newent->teamnodmg;
01726 }
01727 else
01728 {
01729 newent->client->sess.sessionTeam = TEAM_FREE;
01730 }
01731 newent->client->ps.persistant[PERS_TEAM] = newent->client->sess.sessionTeam;
01732
01733 trap_LinkEntity (newent);
01734
01735 if(!ent->use)
01736 {
01737 if( ent->target )
01738 {
01739 G_UseTargets ( ent, ent );
01740 }
01741 if(ent->closetarget)
01742 {
01743 newent->target = ent->closetarget;
01744 }
01745 ent->targetname = NULL;
01746
01747 G_FreeEntity( ent );
01748 }
01749
01750 finish:
01751 if ( ent->spawnflags & NSF_DROP_TO_FLOOR )
01752 {
01753 G_SetOrigin( ent, saveOrg );
01754 }
01755
01756 return newent;
01757 }
01758
01759 void NPC_Spawn_Go(gentity_t *ent)
01760 {
01761 NPC_Spawn_Do(ent);
01762 }
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804 #define SHY_THINK_TIME 1000
01805 #define SHY_SPAWN_DISTANCE 128
01806 #define SHY_SPAWN_DISTANCE_SQR ( SHY_SPAWN_DISTANCE * SHY_SPAWN_DISTANCE )
01807
01808 void NPC_ShySpawn( gentity_t *ent )
01809 {
01810 ent->nextthink = level.time + SHY_THINK_TIME;
01811 ent->think = NPC_ShySpawn;
01812
01813
01814 if ( DistanceSquared( g_entities[0].r.currentOrigin, ent->r.currentOrigin ) <= SHY_SPAWN_DISTANCE_SQR )
01815 return;
01816
01817 if ( (InFOV( ent, &g_entities[0], 80, 64 )) )
01818 if ( (NPC_ClearLOS2( &g_entities[0], ent->r.currentOrigin )) )
01819 return;
01820
01821 ent->think = 0;
01822 ent->nextthink = 0;
01823
01824 NPC_Spawn_Go( ent );
01825 }
01826
01827
01828
01829
01830
01831
01832
01833 void NPC_Spawn ( gentity_t *ent, gentity_t *other, gentity_t *activator )
01834 {
01835
01836 if( ent->delay )
01837 {
01838
01839
01840
01841
01842
01843
01844
01845 if ( ent->spawnflags & 2048 )
01846 {
01847 ent->think = NPC_ShySpawn;
01848 }
01849 else
01850 {
01851 ent->think = NPC_Spawn_Go;
01852 }
01853
01854 ent->nextthink = level.time + ent->delay;
01855 }
01856 else
01857 {
01858 if ( ent->spawnflags & 2048 )
01859 {
01860 NPC_ShySpawn( ent );
01861 }
01862 else
01863 {
01864 NPC_Spawn_Do( ent );
01865 }
01866 }
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953 extern void NPC_PrecacheAnimationCFG( const char *NPC_type );
01954 void NPC_Precache ( gentity_t *spawner );
01955 void NPC_PrecacheType( char *NPC_type )
01956 {
01957 gentity_t *fakespawner = G_Spawn();
01958 if ( fakespawner )
01959 {
01960 fakespawner->NPC_type = NPC_type;
01961 NPC_Precache( fakespawner );
01962
01963 G_FreeEntity( fakespawner );
01964 }
01965 }
01966
01967 void SP_NPC_spawner( gentity_t *self)
01968 {
01969 int t;
01970
01971 if (!g_allowNPC.integer)
01972 {
01973 self->think = G_FreeEntity;
01974 self->nextthink = level.time;
01975 return;
01976 }
01977 if ( !self->fullName || !self->fullName[0] )
01978 {
01979
01980 self->fullName = "Humanoid Lifeform";
01981 }
01982
01983
01984
01985
01986 if(!self->count)
01987 {
01988 self->count = 1;
01989 }
01990
01991 {
01992 static int garbage;
01993
01994 if ( G_SpawnInt( "noBasicSounds", "0", &garbage ) )
01995 {
01996 self->r.svFlags |= SVF_NO_BASIC_SOUNDS;
01997 }
01998 if ( G_SpawnInt( "noCombatSounds", "0", &garbage ) )
01999 {
02000 self->r.svFlags |= SVF_NO_COMBAT_SOUNDS;
02001 }
02002 if ( G_SpawnInt( "noExtraSounds", "0", &garbage ) )
02003 {
02004 self->r.svFlags |= SVF_NO_EXTRA_SOUNDS;
02005 }
02006 }
02007
02008 if ( !self->wait )
02009 {
02010 self->wait = 500;
02011 }
02012 else
02013 {
02014 self->wait *= 1000;
02015 }
02016
02017 self->delay *= 1000;
02018
02019 G_SpawnInt( "showhealth", "0", &t );
02020 if (t)
02021 {
02022 self->s.shouldtarget = qtrue;
02023 }
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033 NPC_PrecacheAnimationCFG( self->NPC_type );
02034
02035
02036 NPC_Precache(self);
02037
02038 if ( self->targetname )
02039 {
02040 self->use = NPC_Spawn;
02041
02042
02043
02044 }
02045 else
02046 {
02047
02048
02049 if (1)
02050 {
02051 self->think = NPC_Spawn_Go;
02052 self->nextthink = level.time + START_TIME_REMOVE_ENTS + 50;
02053 }
02054 else
02055 {
02056 NPC_Spawn( self, self, self );
02057 }
02058 }
02059
02060
02061
02062 }
02063
02064 extern void G_VehicleSpawn( gentity_t *self );
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097 qboolean NPC_VehiclePrecache( gentity_t *spawner )
02098 {
02099 char *droidNPCType = NULL;
02100
02101 vehicleInfo_t *pVehInfo;
02102 int iVehIndex = BG_VehicleGetIndex( spawner->NPC_type );
02103 if ( iVehIndex == VEHICLE_NONE )
02104 {
02105 return qfalse;
02106 }
02107
02108 G_ModelIndex(va("$%s", spawner->NPC_type));
02109
02110 pVehInfo = &g_vehicleInfo[iVehIndex];
02111 if (pVehInfo->model && pVehInfo->model[0])
02112 {
02113 void *tempG2 = NULL;
02114 int skin = 0;
02115 if (pVehInfo->skin && pVehInfo->skin[0])
02116 {
02117 skin = trap_R_RegisterSkin(va("models/players/%s/model_%s.skin", pVehInfo->model, pVehInfo->skin));
02118 }
02119 trap_G2API_InitGhoul2Model(&tempG2, va("models/players/%s/model.glm", pVehInfo->model), 0, skin, 0, 0, 0);
02120 if (tempG2)
02121 {
02122 char GLAName[1024];
02123
02124 GLAName[0] = 0;
02125 trap_G2API_GetGLAName(tempG2, 0, GLAName);
02126
02127 if (GLAName[0])
02128 {
02129 char *slash = Q_strrchr( GLAName, '/' );
02130 if ( slash )
02131 {
02132 strcpy(slash, "/animation.cfg");
02133
02134 BG_ParseAnimationFile(GLAName, NULL, qfalse);
02135 }
02136 }
02137 trap_G2API_CleanGhoul2Models(&tempG2);
02138 }
02139 }
02140
02141
02142 if ( spawner->model2
02143 && spawner->model2[0] )
02144 {
02145 droidNPCType = spawner->model2;
02146 }
02147 else if ( g_vehicleInfo[iVehIndex].droidNPC
02148 && g_vehicleInfo[iVehIndex].droidNPC[0] )
02149 {
02150 droidNPCType = g_vehicleInfo[iVehIndex].droidNPC;
02151 }
02152
02153 if ( droidNPCType )
02154 {
02155 if ( Q_stricmp( "random", droidNPCType ) == 0
02156 || Q_stricmp( "default", droidNPCType ) == 0 )
02157 {
02158 NPC_PrecacheType( "r2d2" );
02159 NPC_PrecacheType( "r5d2" );
02160 }
02161 else
02162 {
02163 NPC_PrecacheType( droidNPCType );
02164 }
02165 }
02166 return qtrue;
02167 }
02168
02169 void NPC_VehicleSpawnUse( gentity_t *self, gentity_t *other, gentity_t *activator )
02170 {
02171 if ( self->delay )
02172 {
02173 self->think = G_VehicleSpawn;
02174 self->nextthink = level.time + self->delay;
02175 }
02176 else
02177 {
02178 G_VehicleSpawn( self );
02179 }
02180 }
02181
02182 void SP_NPC_Vehicle( gentity_t *self)
02183 {
02184 float dropTime;
02185 int t;
02186 if ( !self->NPC_type )
02187 {
02188 self->NPC_type = "swoop";
02189 }
02190
02191 if ( !self->classname )
02192 {
02193 self->classname = "NPC_Vehicle";
02194 }
02195
02196 if ( !self->wait )
02197 {
02198 self->wait = 500;
02199 }
02200 else
02201 {
02202 self->wait *= 1000;
02203 }
02204 self->delay *= 1000;
02205
02206 G_SetOrigin( self, self->s.origin );
02207 G_SetAngles( self, self->s.angles );
02208 G_SpawnFloat( "dropTime", "0", &dropTime );
02209 if ( dropTime )
02210 {
02211 self->fly_sound_debounce_time = ceil(dropTime*1000.0);
02212 }
02213
02214 G_SpawnInt( "showhealth", "0", &t );
02215 if (t)
02216 {
02217 self->s.shouldtarget = qtrue;
02218 }
02219
02220
02221 if ( self->targetname )
02222 {
02223 if ( !NPC_VehiclePrecache( self ) )
02224 {
02225 G_FreeEntity( self );
02226 return;
02227 }
02228 self->use = NPC_VehicleSpawnUse;
02229 }
02230 else
02231 {
02232 if ( self->delay )
02233 {
02234 if ( !NPC_VehiclePrecache( self ) )
02235 {
02236 G_FreeEntity( self );
02237 return;
02238 }
02239 self->think = G_VehicleSpawn;
02240 self->nextthink = level.time + self->delay;
02241 }
02242 else
02243 {
02244 G_VehicleSpawn( self );
02245 }
02246 }
02247 }
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332 void SP_NPC_Kyle( gentity_t *self)
02333 {
02334 self->NPC_type = "Kyle";
02335
02336 WP_SetSaberModel( NULL, CLASS_KYLE );
02337
02338 SP_NPC_spawner( self );
02339 }
02340
02341
02342
02343
02344
02345
02346
02347
02348 void SP_NPC_Lando( gentity_t *self)
02349 {
02350 self->NPC_type = "Lando";
02351
02352 SP_NPC_spawner( self );
02353 }
02354
02355
02356
02357
02358
02359
02360
02361
02362 void SP_NPC_Jan( gentity_t *self)
02363 {
02364 self->NPC_type = "Jan";
02365
02366 SP_NPC_spawner( self );
02367 }
02368
02369
02370
02371
02372
02373
02374
02375
02376 void SP_NPC_Luke( gentity_t *self)
02377 {
02378 self->NPC_type = "Luke";
02379
02380 WP_SetSaberModel( NULL, CLASS_LUKE );
02381
02382 SP_NPC_spawner( self );
02383 }
02384
02385
02386
02387
02388
02389
02390
02391
02392 void SP_NPC_MonMothma( gentity_t *self)
02393 {
02394 self->NPC_type = "MonMothma";
02395
02396 SP_NPC_spawner( self );
02397 }
02398
02399
02400
02401
02402
02403
02404
02405
02406 void SP_NPC_Tavion( gentity_t *self)
02407 {
02408 self->NPC_type = "Tavion";
02409
02410 WP_SetSaberModel( NULL, CLASS_TAVION );
02411
02412 SP_NPC_spawner( self );
02413 }
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426 void SP_NPC_Tavion_New( gentity_t *self)
02427 {
02428 if ( (self->spawnflags&1) )
02429 {
02430 self->NPC_type = "tavion_scepter";
02431 }
02432 else if ( (self->spawnflags&2) )
02433 {
02434 self->NPC_type = "tavion_sith_sword";
02435 }
02436 else
02437 {
02438 self->NPC_type = "tavion_new";
02439 }
02440
02441 SP_NPC_spawner( self );
02442 }
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454 void SP_NPC_Alora( gentity_t *self)
02455 {
02456 if ( (self->spawnflags&1) )
02457 {
02458 self->NPC_type = "alora_dual";
02459 }
02460 else
02461 {
02462 self->NPC_type = "alora";
02463 }
02464
02465 SP_NPC_spawner( self );
02466 }
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481 void SP_NPC_Reborn_New( gentity_t *self)
02482 {
02483 if ( !self->NPC_type )
02484 {
02485 if ( (self->spawnflags&4) )
02486 {
02487 if ( (self->spawnflags&1) )
02488 {
02489 self->NPC_type = "reborn_dual2";
02490 }
02491 else if ( (self->spawnflags&2) )
02492 {
02493 self->NPC_type = "reborn_staff2";
02494 }
02495 else
02496 {
02497 self->NPC_type = "reborn_new2";
02498 }
02499 }
02500 else
02501 {
02502 if ( (self->spawnflags&1) )
02503 {
02504 self->NPC_type = "reborn_dual";
02505 }
02506 else if ( (self->spawnflags&2) )
02507 {
02508 self->NPC_type = "reborn_staff";
02509 }
02510 else
02511 {
02512 self->NPC_type = "reborn_new";
02513 }
02514 }
02515 }
02516
02517 SP_NPC_spawner( self );
02518 }
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536 void SP_NPC_Cultist_Saber( gentity_t *self)
02537 {
02538 if ( !self->NPC_type )
02539 {
02540 if ( (self->spawnflags&1) )
02541 {
02542 if ( (self->spawnflags&8) )
02543 {
02544 self->NPC_type = "cultist_saber_med_throw";
02545 }
02546 else
02547 {
02548 self->NPC_type = "cultist_saber_med";
02549 }
02550 }
02551 else if ( (self->spawnflags&2) )
02552 {
02553 if ( (self->spawnflags&8) )
02554 {
02555 self->NPC_type = "cultist_saber_strong_throw";
02556 }
02557 else
02558 {
02559 self->NPC_type = "cultist_saber_strong";
02560 }
02561 }
02562 else if ( (self->spawnflags&2) )
02563 {
02564 if ( (self->spawnflags&8) )
02565 {
02566 self->NPC_type = "cultist_saber_all_throw";
02567 }
02568 else
02569 {
02570 self->NPC_type = "cultist_saber_all";
02571 }
02572 }
02573 else
02574 {
02575 if ( (self->spawnflags&8) )
02576 {
02577 self->NPC_type = "cultist_saber_throw";
02578 }
02579 else
02580 {
02581 self->NPC_type = "cultist_saber";
02582 }
02583 }
02584 }
02585
02586 SP_NPC_spawner( self );
02587 }
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605 void SP_NPC_Cultist_Saber_Powers( gentity_t *self)
02606 {
02607 if ( !self->NPC_type )
02608 {
02609 if ( (self->spawnflags&1) )
02610 {
02611 if ( (self->spawnflags&8) )
02612 {
02613 self->NPC_type = "cultist_saber_med_throw2";
02614 }
02615 else
02616 {
02617 self->NPC_type = "cultist_saber_med2";
02618 }
02619 }
02620 else if ( (self->spawnflags&2) )
02621 {
02622 if ( (self->spawnflags&8) )
02623 {
02624 self->NPC_type = "cultist_saber_strong_throw2";
02625 }
02626 else
02627 {
02628 self->NPC_type = "cultist_saber_strong2";
02629 }
02630 }
02631 else if ( (self->spawnflags&2) )
02632 {
02633 if ( (self->spawnflags&8) )
02634 {
02635 self->NPC_type = "cultist_saber_all_throw2";
02636 }
02637 else
02638 {
02639 self->NPC_type = "cultist_saber_all2";
02640 }
02641 }
02642 else
02643 {
02644 if ( (self->spawnflags&8) )
02645 {
02646 self->NPC_type = "cultist_saber_throw";
02647 }
02648 else
02649 {
02650 self->NPC_type = "cultist_saber2";
02651 }
02652 }
02653 }
02654
02655 SP_NPC_spawner( self );
02656 }
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673 void SP_NPC_Cultist( gentity_t *self)
02674 {
02675 if ( !self->NPC_type )
02676 {
02677 if ( (self->spawnflags&1) )
02678 {
02679 self->NPC_type = NULL;
02680 self->spawnflags = 0;
02681 switch ( Q_irand( 0, 2 ) )
02682 {
02683 case 0:
02684 self->spawnflags |= 1;
02685 break;
02686 case 1:
02687 self->spawnflags |= 2;
02688 break;
02689 case 2:
02690 self->spawnflags |= 4;
02691 break;
02692 }
02693 if ( Q_irand( 0, 1 ) )
02694 {
02695 self->spawnflags |= 8;
02696 }
02697 SP_NPC_Cultist_Saber( self );
02698 return;
02699 }
02700 else if ( (self->spawnflags&2) )
02701 {
02702 self->NPC_type = "cultist_grip";
02703 }
02704 else if ( (self->spawnflags&4) )
02705 {
02706 self->NPC_type = "cultist_lightning";
02707 }
02708 else if ( (self->spawnflags&8) )
02709 {
02710 self->NPC_type = "cultist_drain";
02711 }
02712 else
02713 {
02714 self->NPC_type = "cultist";
02715 }
02716 }
02717
02718 SP_NPC_spawner( self );
02719 }
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731 void SP_NPC_Cultist_Commando( gentity_t *self)
02732 {
02733 if ( !self->NPC_type )
02734 {
02735 self->NPC_type = "cultistcommando";
02736 }
02737 SP_NPC_spawner( self );
02738 }
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749 void SP_NPC_Cultist_Destroyer( gentity_t *self)
02750 {
02751 self->NPC_type = "cultist";
02752 SP_NPC_spawner( self );
02753 }
02754
02755
02756
02757
02758
02759
02760
02761
02762 void SP_NPC_Reelo( gentity_t *self)
02763 {
02764 self->NPC_type = "Reelo";
02765
02766 SP_NPC_spawner( self );
02767 }
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778 void SP_NPC_Galak( gentity_t *self)
02779 {
02780 if ( self->spawnflags & 1 )
02781 {
02782 self->NPC_type = "Galak_Mech";
02783 NPC_GalakMech_Precache();
02784 }
02785 else
02786 {
02787 self->NPC_type = "Galak";
02788 }
02789
02790 SP_NPC_spawner( self );
02791 }
02792
02793
02794
02795
02796
02797
02798
02799
02800 void SP_NPC_Desann( gentity_t *self)
02801 {
02802 self->NPC_type = "Desann";
02803
02804 WP_SetSaberModel( NULL, CLASS_DESANN );
02805
02806 SP_NPC_spawner( self );
02807 }
02808
02809
02810
02811
02812
02813
02814
02815
02816 void SP_NPC_Bartender( gentity_t *self)
02817 {
02818 self->NPC_type = "Bartender";
02819
02820 SP_NPC_spawner( self );
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830 void SP_NPC_MorganKatarn( gentity_t *self)
02831 {
02832 self->NPC_type = "MorganKatarn";
02833
02834 SP_NPC_spawner( self );
02835 }
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851 void SP_NPC_Jedi( gentity_t *self)
02852 {
02853 if(!self->NPC_type)
02854 {
02855 if ( self->spawnflags & 1 )
02856 {
02857 self->NPC_type = "jeditrainer";
02858 }
02859 else
02860 {
02861
02862
02863
02864
02865
02866
02867 if ( Q_irand( 0, 1 ) )
02868 {
02869 self->NPC_type = "Jedi";
02870 }
02871 else
02872 {
02873 self->NPC_type = "Jedi2";
02874 }
02875 }
02876 }
02877
02878 WP_SetSaberModel( NULL, CLASS_JEDI );
02879
02880 SP_NPC_spawner( self );
02881 }
02882
02883
02884
02885
02886
02887
02888
02889
02890 void SP_NPC_Prisoner( gentity_t *self)
02891 {
02892 if(!self->NPC_type)
02893 {
02894 if ( Q_irand( 0, 1 ) )
02895 {
02896 self->NPC_type = "Prisoner";
02897 }
02898 else
02899 {
02900 self->NPC_type = "Prisoner2";
02901 }
02902 }
02903
02904 SP_NPC_spawner( self );
02905 }
02906
02907
02908
02909
02910
02911
02912
02913
02914 void SP_NPC_Rebel( gentity_t *self)
02915 {
02916 if(!self->NPC_type)
02917 {
02918 if ( Q_irand( 0, 1 ) )
02919 {
02920 self->NPC_type = "Rebel";
02921 }
02922 else
02923 {
02924 self->NPC_type = "Rebel2";
02925 }
02926 }
02927
02928 SP_NPC_spawner( self );
02929 }
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949 void SP_NPC_Stormtrooper( gentity_t *self)
02950 {
02951 if ( self->spawnflags & 8 )
02952 {
02953 self->NPC_type = "rockettrooper";
02954 }
02955 else if ( self->spawnflags & 4 )
02956 {
02957 self->NPC_type = "stofficeralt";
02958 }
02959 else if ( self->spawnflags & 2 )
02960 {
02961 self->NPC_type = "stcommander";
02962 }
02963 else if ( self->spawnflags & 1 )
02964 {
02965 self->NPC_type = "stofficer";
02966 }
02967 else
02968 {
02969 if ( Q_irand( 0, 1 ) )
02970 {
02971 self->NPC_type = "StormTrooper";
02972 }
02973 else
02974 {
02975 self->NPC_type = "StormTrooper2";
02976 }
02977 }
02978
02979 SP_NPC_spawner( self );
02980 }
02981 void SP_NPC_StormtrooperOfficer( gentity_t *self)
02982 {
02983 self->spawnflags |= 1;
02984 SP_NPC_Stormtrooper( self );
02985 }
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995 void SP_NPC_Snowtrooper( gentity_t *self)
02996 {
02997 self->NPC_type = "snowtrooper";
02998
02999 SP_NPC_spawner( self );
03000 }
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010 void SP_NPC_Tie_Pilot( gentity_t *self)
03011 {
03012 self->NPC_type = "stormpilot";
03013
03014 SP_NPC_spawner( self );
03015 }
03016
03017
03018
03019
03020
03021
03022
03023
03024 void SP_NPC_Ugnaught( gentity_t *self)
03025 {
03026 if ( !self->NPC_type )
03027 {
03028 if ( Q_irand( 0, 1 ) )
03029 {
03030 self->NPC_type = "Ugnaught";
03031 }
03032 else
03033 {
03034 self->NPC_type = "Ugnaught2";
03035 }
03036 }
03037
03038 SP_NPC_spawner( self );
03039 }
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050 void SP_NPC_Jawa( gentity_t *self)
03051 {
03052 if ( !self->NPC_type )
03053 {
03054 if ( (self->spawnflags&1) )
03055 {
03056 self->NPC_type = "jawa_armed";
03057 }
03058 else
03059 {
03060 self->NPC_type = "jawa";
03061 }
03062 }
03063
03064 SP_NPC_spawner( self );
03065 }
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078 void SP_NPC_Gran( gentity_t *self)
03079 {
03080 if ( !self->NPC_type )
03081 {
03082 if ( self->spawnflags & 1 )
03083 {
03084 self->NPC_type = "granshooter";
03085 }
03086 else if ( self->spawnflags & 2 )
03087 {
03088 self->NPC_type = "granboxer";
03089 }
03090 else
03091 {
03092 if ( Q_irand( 0, 1 ) )
03093 {
03094 self->NPC_type = "gran";
03095 }
03096 else
03097 {
03098 self->NPC_type = "gran2";
03099 }
03100 }
03101 }
03102
03103 SP_NPC_spawner( self );
03104 }
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 void SP_NPC_Rodian( gentity_t *self)
03116 {
03117 if ( !self->NPC_type )
03118 {
03119 if ( self->spawnflags&1 )
03120 {
03121 self->NPC_type = "rodian2";
03122 }
03123 else
03124 {
03125 self->NPC_type = "rodian";
03126 }
03127 }
03128
03129 SP_NPC_spawner( self );
03130 }
03131
03132
03133
03134
03135
03136
03137
03138
03139 void SP_NPC_Weequay( gentity_t *self)
03140 {
03141 if ( !self->NPC_type )
03142 {
03143 switch ( Q_irand( 0, 3 ) )
03144 {
03145 case 0:
03146 self->NPC_type = "Weequay";
03147 break;
03148 case 1:
03149 self->NPC_type = "Weequay2";
03150 break;
03151 case 2:
03152 self->NPC_type = "Weequay3";
03153 break;
03154 case 3:
03155 self->NPC_type = "Weequay4";
03156 break;
03157 }
03158 }
03159
03160 SP_NPC_spawner( self );
03161 }
03162
03163
03164
03165
03166
03167
03168
03169
03170 void SP_NPC_Trandoshan( gentity_t *self)
03171 {
03172 if ( !self->NPC_type )
03173 {
03174 self->NPC_type = "Trandoshan";
03175 }
03176
03177 SP_NPC_spawner( self );
03178 }
03179
03180
03181
03182
03183
03184
03185
03186
03187 void SP_NPC_Tusken( gentity_t *self)
03188 {
03189 if ( !self->NPC_type )
03190 {
03191 if ( (self->spawnflags&1) )
03192 {
03193 self->NPC_type = "tuskensniper";
03194 }
03195 else
03196 {
03197 self->NPC_type = "tusken";
03198 }
03199 }
03200
03201 SP_NPC_spawner( self );
03202 }
03203
03204
03205
03206
03207
03208
03209
03210
03211 void SP_NPC_Noghri( gentity_t *self)
03212 {
03213 if ( !self->NPC_type )
03214 {
03215 self->NPC_type = "noghri";
03216 }
03217
03218 SP_NPC_spawner( self );
03219 }
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229 void SP_NPC_SwampTrooper( gentity_t *self)
03230 {
03231 if ( !self->NPC_type )
03232 {
03233 if ( self->spawnflags & 1 )
03234 {
03235 self->NPC_type = "SwampTrooper2";
03236 }
03237 else
03238 {
03239 self->NPC_type = "SwampTrooper";
03240 }
03241 }
03242
03243 SP_NPC_spawner( self );
03244 }
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261 void SP_NPC_Imperial( gentity_t *self)
03262 {
03263 if ( !self->NPC_type )
03264 {
03265 if ( self->spawnflags & 1 )
03266 {
03267 self->NPC_type = "ImpOfficer";
03268 }
03269 else if ( self->spawnflags & 2 )
03270 {
03271 self->NPC_type = "ImpCommander";
03272 }
03273 else
03274 {
03275 self->NPC_type = "Imperial";
03276 }
03277 }
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294 SP_NPC_spawner( self );
03295 }
03296
03297
03298
03299
03300
03301
03302
03303
03304 void SP_NPC_ImpWorker( gentity_t *self)
03305 {
03306 if ( !self->NPC_type )
03307 {
03308 if ( !Q_irand( 0, 2 ) )
03309 {
03310 self->NPC_type = "ImpWorker";
03311 }
03312 else if ( Q_irand( 0, 1 ) )
03313 {
03314 self->NPC_type = "ImpWorker2";
03315 }
03316 else
03317 {
03318 self->NPC_type = "ImpWorker3";
03319 }
03320 }
03321
03322 SP_NPC_spawner( self );
03323 }
03324
03325
03326
03327
03328
03329
03330
03331
03332 void SP_NPC_BespinCop( gentity_t *self)
03333 {
03334 if ( !self->NPC_type )
03335 {
03336 if ( !Q_irand( 0, 1 ) )
03337 {
03338 self->NPC_type = "BespinCop";
03339 }
03340 else
03341 {
03342 self->NPC_type = "BespinCop2";
03343 }
03344 }
03345
03346 SP_NPC_spawner( self );
03347 }
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366 void SP_NPC_Reborn( gentity_t *self)
03367 {
03368 if ( !self->NPC_type )
03369 {
03370 if ( self->spawnflags & 1 )
03371 {
03372 self->NPC_type = "rebornforceuser";
03373 }
03374 else if ( self->spawnflags & 2 )
03375 {
03376 self->NPC_type = "rebornfencer";
03377 }
03378 else if ( self->spawnflags & 4 )
03379 {
03380 self->NPC_type = "rebornacrobat";
03381 }
03382 else if ( self->spawnflags & 8 )
03383 {
03384 self->NPC_type = "rebornboss";
03385 }
03386 else
03387 {
03388 self->NPC_type = "reborn";
03389 }
03390 }
03391
03392 WP_SetSaberModel( NULL, CLASS_REBORN );
03393 SP_NPC_spawner( self );
03394 }
03395
03396
03397
03398
03399
03400
03401
03402
03403 void SP_NPC_ShadowTrooper( gentity_t *self)
03404 {
03405 if(!self->NPC_type)
03406 {
03407 if ( !Q_irand( 0, 1 ) )
03408 {
03409 self->NPC_type = "ShadowTrooper";
03410 }
03411 else
03412 {
03413 self->NPC_type = "ShadowTrooper2";
03414 }
03415 }
03416
03417 NPC_ShadowTrooper_Precache();
03418 WP_SetSaberModel( NULL, CLASS_SHADOWTROOPER );
03419
03420 SP_NPC_spawner( self );
03421 }
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433 void SP_NPC_Monster_Murjj( gentity_t *self)
03434 {
03435 self->NPC_type = "Murjj";
03436
03437 SP_NPC_spawner( self );
03438 }
03439
03440
03441
03442
03443
03444
03445
03446
03447 void SP_NPC_Monster_Swamp( gentity_t *self)
03448 {
03449 self->NPC_type = "Swamp";
03450
03451 SP_NPC_spawner( self );
03452 }
03453
03454
03455
03456
03457
03458
03459
03460
03461 void SP_NPC_Monster_Howler( gentity_t *self)
03462 {
03463 self->NPC_type = "howler";
03464
03465 SP_NPC_spawner( self );
03466 }
03467
03468
03469
03470
03471
03472
03473
03474
03475 void SP_NPC_MineMonster( gentity_t *self)
03476 {
03477 self->NPC_type = "minemonster";
03478
03479 SP_NPC_spawner( self );
03480 NPC_MineMonster_Precache();
03481 }
03482
03483
03484
03485
03486
03487
03488
03489
03490 void SP_NPC_Monster_Claw( gentity_t *self)
03491 {
03492 self->NPC_type = "Claw";
03493
03494 SP_NPC_spawner( self );
03495 }
03496
03497
03498
03499
03500
03501
03502
03503
03504 void SP_NPC_Monster_Glider( gentity_t *self)
03505 {
03506 self->NPC_type = "Glider";
03507
03508 SP_NPC_spawner( self );
03509 }
03510
03511
03512
03513
03514
03515
03516
03517
03518 void SP_NPC_Monster_Flier2( gentity_t *self)
03519 {
03520 self->NPC_type = "Flier2";
03521
03522 SP_NPC_spawner( self );
03523 }
03524
03525
03526
03527
03528
03529
03530
03531
03532 void SP_NPC_Monster_Lizard( gentity_t *self)
03533 {
03534 self->NPC_type = "Lizard";
03535
03536 SP_NPC_spawner( self );
03537 }
03538
03539
03540
03541
03542
03543
03544
03545
03546 void SP_NPC_Monster_Fish( gentity_t *self)
03547 {
03548 self->NPC_type = "Fish";
03549
03550 SP_NPC_spawner( self );
03551 }
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562 void SP_NPC_Monster_Wampa( gentity_t *self)
03563 {
03564 self->NPC_type = "wampa";
03565
03566 NPC_Wampa_Precache();
03567
03568 SP_NPC_spawner( self );
03569 }
03570
03571
03572
03573
03574
03575
03576
03577
03578 void SP_NPC_Monster_Rancor( gentity_t *self)
03579 {
03580 self->NPC_type = "rancor";
03581
03582 SP_NPC_spawner( self );
03583 }
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596 void SP_NPC_Droid_Interrogator( gentity_t *self)
03597 {
03598 self->NPC_type = "interrogator";
03599
03600 SP_NPC_spawner( self );
03601
03602 NPC_Interrogator_Precache(self);
03603 }
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614 void SP_NPC_Droid_Probe( gentity_t *self)
03615 {
03616 self->NPC_type = "probe";
03617
03618 SP_NPC_spawner( self );
03619
03620 NPC_Probe_Precache();
03621 }
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633 void SP_NPC_Droid_Mark1( gentity_t *self)
03634 {
03635 self->NPC_type = "mark1";
03636
03637 SP_NPC_spawner( self );
03638
03639 NPC_Mark1_Precache();
03640 }
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652 void SP_NPC_Droid_Mark2( gentity_t *self)
03653 {
03654 self->NPC_type = "mark2";
03655
03656 SP_NPC_spawner( self );
03657
03658 NPC_Mark2_Precache();
03659 }
03660
03661
03662
03663
03664
03665
03666
03667
03668 void SP_NPC_Droid_ATST( gentity_t *self)
03669 {
03670 if ( (self->spawnflags&1) )
03671 {
03672 self->NPC_type = "atst_vehicle";
03673 }
03674 else
03675 {
03676 self->NPC_type = "atst";
03677 }
03678
03679 SP_NPC_spawner( self );
03680
03681 NPC_ATST_Precache();
03682 }
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 void SP_NPC_Droid_Remote( gentity_t *self)
03694 {
03695 self->NPC_type = "remote";
03696
03697 SP_NPC_spawner( self );
03698
03699 NPC_Remote_Precache();
03700 }
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711 void SP_NPC_Droid_Seeker( gentity_t *self)
03712 {
03713 self->NPC_type = "seeker";
03714
03715 SP_NPC_spawner( self );
03716
03717 NPC_Seeker_Precache();
03718 }
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729 void SP_NPC_Droid_Sentry( gentity_t *self)
03730 {
03731 self->NPC_type = "sentry";
03732
03733 SP_NPC_spawner( self );
03734
03735 NPC_Sentry_Precache();
03736 }
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749 void SP_NPC_Droid_Gonk( gentity_t *self)
03750 {
03751 self->NPC_type = "gonk";
03752
03753 SP_NPC_spawner( self );
03754
03755
03756 NPC_Gonk_Precache();
03757 }
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770 void SP_NPC_Droid_Mouse( gentity_t *self)
03771 {
03772 self->NPC_type = "mouse";
03773
03774 SP_NPC_spawner( self );
03775
03776
03777 NPC_Mouse_Precache();
03778
03779 }
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792 void SP_NPC_Droid_R2D2( gentity_t *self)
03793 {
03794 if ( self->spawnflags&1 )
03795 {
03796 self->NPC_type = "r2d2_imp";
03797 }
03798 else
03799 {
03800 self->NPC_type = "r2d2";
03801 }
03802
03803 SP_NPC_spawner( self );
03804
03805 NPC_R2D2_Precache();
03806 }
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820 void SP_NPC_Droid_R5D2( gentity_t *self)
03821 {
03822 if ( self->spawnflags&1 )
03823 {
03824 self->NPC_type = "r5d2_imp";
03825 }
03826 else
03827 {
03828 self->NPC_type = "r5d2";
03829 }
03830
03831 SP_NPC_spawner( self );
03832
03833 NPC_R5D2_Precache();
03834 }
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845 void SP_NPC_Droid_Protocol( gentity_t *self)
03846 {
03847 if ( self->spawnflags&1 )
03848 {
03849 self->NPC_type = "protocol_imp";
03850 }
03851 else
03852 {
03853 self->NPC_type = "protocol";
03854 }
03855
03856 SP_NPC_spawner( self );
03857 NPC_Protocol_Precache();
03858 }
03859
03860
03861
03862
03863
03864
03865
03866 gentity_t *NPC_SpawnType( gentity_t *ent, char *npc_type, char *targetname, qboolean isVehicle )
03867 {
03868 gentity_t *NPCspawner = G_Spawn();
03869 vec3_t forward, end;
03870 trace_t trace;
03871
03872 if(!NPCspawner)
03873 {
03874 Com_Printf( S_COLOR_RED"NPC_Spawn Error: Out of entities!\n" );
03875 return NULL;
03876 }
03877
03878 NPCspawner->think = G_FreeEntity;
03879 NPCspawner->nextthink = level.time + FRAMETIME;
03880
03881 if ( !npc_type )
03882 {
03883 return NULL;
03884 }
03885
03886 if (!npc_type[0])
03887 {
03888 Com_Printf( S_COLOR_RED"Error, expected one of:\n"S_COLOR_WHITE" NPC spawn [NPC type (from ext_data/NPCs)]\n NPC spawn vehicle [VEH type (from ext_data/vehicles)]\n" );
03889 return NULL;
03890 }
03891
03892 if ( !ent || !ent->client )
03893 {
03894 return NULL;
03895 }
03896
03897
03898
03899
03900 AngleVectors(ent->client->ps.viewangles, forward, NULL, NULL);
03901 VectorNormalize(forward);
03902 VectorMA(ent->r.currentOrigin, 64, forward, end);
03903 trap_Trace(&trace, ent->r.currentOrigin, NULL, NULL, end, 0, MASK_SOLID);
03904 VectorCopy(trace.endpos, end);
03905 end[2] -= 24;
03906 trap_Trace(&trace, trace.endpos, NULL, NULL, end, 0, MASK_SOLID);
03907 VectorCopy(trace.endpos, end);
03908 end[2] += 24;
03909 G_SetOrigin(NPCspawner, end);
03910 VectorCopy(NPCspawner->r.currentOrigin, NPCspawner->s.origin);
03911
03912 NPCspawner->s.angles[1] = ent->client->ps.viewangles[1];
03913
03914 trap_LinkEntity(NPCspawner);
03915
03916 NPCspawner->NPC_type = G_NewString( npc_type );
03917
03918 if ( targetname )
03919 {
03920 NPCspawner->NPC_targetname = G_NewString(targetname);
03921 }
03922
03923 NPCspawner->count = 1;
03924
03925 NPCspawner->delay = 0;
03926
03927
03928
03929
03930
03931
03932 if ( isVehicle )
03933 {
03934 NPCspawner->classname = "NPC_Vehicle";
03935 }
03936
03937
03938 if ( !Q_stricmp( "gonk", NPCspawner->NPC_type))
03939 {
03940 NPC_Gonk_Precache();
03941 }
03942 else if ( !Q_stricmp( "mouse", NPCspawner->NPC_type))
03943 {
03944 NPC_Mouse_Precache();
03945 }
03946 else if ( !Q_strncmp( "r2d2", NPCspawner->NPC_type, 4))
03947 {
03948 NPC_R2D2_Precache();
03949 }
03950 else if ( !Q_stricmp( "atst", NPCspawner->NPC_type))
03951 {
03952 NPC_ATST_Precache();
03953 }
03954 else if ( !Q_strncmp( "r5d2", NPCspawner->NPC_type, 4))
03955 {
03956 NPC_R5D2_Precache();
03957 }
03958 else if ( !Q_stricmp( "mark1", NPCspawner->NPC_type))
03959 {
03960 NPC_Mark1_Precache();
03961 }
03962 else if ( !Q_stricmp( "mark2", NPCspawner->NPC_type))
03963 {
03964 NPC_Mark2_Precache();
03965 }
03966 else if ( !Q_stricmp( "interrogator", NPCspawner->NPC_type))
03967 {
03968 NPC_Interrogator_Precache(NULL);
03969 }
03970 else if ( !Q_stricmp( "probe", NPCspawner->NPC_type))
03971 {
03972 NPC_Probe_Precache();
03973 }
03974 else if ( !Q_stricmp( "seeker", NPCspawner->NPC_type))
03975 {
03976 NPC_Seeker_Precache();
03977 }
03978 else if ( !Q_stricmp( "remote", NPCspawner->NPC_type))
03979 {
03980 NPC_Remote_Precache();
03981 }
03982 else if ( !Q_strncmp( "shadowtrooper", NPCspawner->NPC_type, 13 ) )
03983 {
03984 NPC_ShadowTrooper_Precache();
03985 }
03986 else if ( !Q_stricmp( "minemonster", NPCspawner->NPC_type ))
03987 {
03988 NPC_MineMonster_Precache();
03989 }
03990 else if ( !Q_stricmp( "howler", NPCspawner->NPC_type ))
03991 {
03992 NPC_Howler_Precache();
03993 }
03994 else if ( !Q_stricmp( "sentry", NPCspawner->NPC_type ))
03995 {
03996 NPC_Sentry_Precache();
03997 }
03998 else if ( !Q_stricmp( "protocol", NPCspawner->NPC_type ))
03999 {
04000 NPC_Protocol_Precache();
04001 }
04002 else if ( !Q_stricmp( "galak_mech", NPCspawner->NPC_type ))
04003 {
04004 NPC_GalakMech_Precache();
04005 }
04006 else if ( !Q_stricmp( "wampa", NPCspawner->NPC_type ))
04007 {
04008 NPC_Wampa_Precache();
04009 }
04010
04011 return (NPC_Spawn_Do( NPCspawner ));
04012 }
04013
04014 void NPC_Spawn_f( gentity_t *ent )
04015 {
04016 char npc_type[1024];
04017 char targetname[1024];
04018 qboolean isVehicle = qfalse;
04019
04020 trap_Argv(2, npc_type, 1024);
04021 if ( Q_stricmp( "vehicle", npc_type ) == 0 )
04022 {
04023 isVehicle = qtrue;
04024 trap_Argv(3, npc_type, 1024);
04025 trap_Argv(4, targetname, 1024);
04026 }
04027 else
04028 {
04029 trap_Argv(3, targetname, 1024);
04030 }
04031
04032 NPC_SpawnType( ent, npc_type, targetname, isVehicle );
04033 }
04034
04035
04036
04037
04038 extern stringID_table_t TeamTable[];
04039 void NPC_Kill_f( void )
04040 {
04041 int n;
04042 gentity_t *player;
04043 char name[1024];
04044 team_t killTeam = TEAM_FREE;
04045 qboolean killNonSF = qfalse;
04046
04047 trap_Argv(2, name, 1024);
04048
04049 if ( !name[0] )
04050 {
04051 Com_Printf( S_COLOR_RED"Error, Expected:\n");
04052 Com_Printf( S_COLOR_RED"NPC kill '[NPC targetname]' - kills NPCs with certain targetname\n" );
04053 Com_Printf( S_COLOR_RED"or\n" );
04054 Com_Printf( S_COLOR_RED"NPC kill 'all' - kills all NPCs\n" );
04055 Com_Printf( S_COLOR_RED"or\n" );
04056 Com_Printf( S_COLOR_RED"NPC team '[teamname]' - kills all NPCs of a certain team ('nonally' is all but your allies)\n" );
04057 return;
04058 }
04059
04060 if ( Q_stricmp( "team", name ) == 0 )
04061 {
04062 trap_Argv(3, name, 1024);
04063
04064 if ( !name[0] )
04065 {
04066 Com_Printf( S_COLOR_RED"NPC_Kill Error: 'npc kill team' requires a team name!\n" );
04067 Com_Printf( S_COLOR_RED"Valid team names are:\n");
04068 for ( n = (TEAM_FREE + 1); n < TEAM_NUM_TEAMS; n++ )
04069 {
04070 Com_Printf( S_COLOR_RED"%s\n", TeamNames[n] );
04071 }
04072 Com_Printf( S_COLOR_RED"nonally - kills all but your teammates\n" );
04073 return;
04074 }
04075
04076 if ( Q_stricmp( "nonally", name ) == 0 )
04077 {
04078 killNonSF = qtrue;
04079 }
04080 else
04081 {
04082 killTeam = (team_t)GetIDForString( TeamTable, name );
04083
04084 if ( killTeam == TEAM_FREE )
04085 {
04086 Com_Printf( S_COLOR_RED"NPC_Kill Error: team '%s' not recognized\n", name );
04087 Com_Printf( S_COLOR_RED"Valid team names are:\n");
04088 for ( n = (TEAM_FREE + 1); n < TEAM_NUM_TEAMS; n++ )
04089 {
04090 Com_Printf( S_COLOR_RED"%s\n", TeamNames[n] );
04091 }
04092 Com_Printf( S_COLOR_RED"nonally - kills all but your teammates\n" );
04093 return;
04094 }
04095 }
04096 }
04097
04098 for ( n = 1; n < ENTITYNUM_MAX_NORMAL; n++)
04099 {
04100 player = &g_entities[n];
04101 if (!player->inuse) {
04102 continue;
04103 }
04104 if ( killNonSF )
04105 {
04106 if ( player )
04107 {
04108 if ( player->client )
04109 {
04110 if ( player->client->playerTeam != NPCTEAM_PLAYER )
04111 {
04112 Com_Printf( S_COLOR_GREEN"Killing NPC %s named %s\n", player->NPC_type, player->targetname );
04113 player->health = 0;
04114
04115 if (player->die && player->client)
04116 {
04117 player->die(player, player, player, player->client->pers.maxHealth, MOD_UNKNOWN);
04118 }
04119 }
04120 }
04121 else if ( player->NPC_type && player->classname && player->classname[0] && Q_stricmp( "NPC_starfleet", player->classname ) != 0 )
04122 {
04123 Com_Printf( S_COLOR_GREEN"Removing NPC spawner %s with NPC named %s\n", player->NPC_type, player->NPC_targetname );
04124 G_FreeEntity( player );
04125
04126 }
04127 }
04128 }
04129 else if ( player && player->NPC && player->client )
04130 {
04131 if ( killTeam != TEAM_FREE )
04132 {
04133 if ( player->client->playerTeam == killTeam )
04134 {
04135 Com_Printf( S_COLOR_GREEN"Killing NPC %s named %s\n", player->NPC_type, player->targetname );
04136 player->health = 0;
04137 if (player->die)
04138 {
04139 player->die(player, player, player, player->client->pers.maxHealth, MOD_UNKNOWN);
04140 }
04141 }
04142 }
04143 else if( (player->targetname && Q_stricmp( name, player->targetname ) == 0)
04144 || Q_stricmp( name, "all" ) == 0 )
04145 {
04146 Com_Printf( S_COLOR_GREEN"Killing NPC %s named %s\n", player->NPC_type, player->targetname );
04147 player->health = 0;
04148 player->client->ps.stats[STAT_HEALTH] = 0;
04149 if (player->die)
04150 {
04151 player->die(player, player, player, 100, MOD_UNKNOWN);
04152 }
04153 }
04154 }
04155
04156
04157
04158
04159
04160
04161
04162
04163 }
04164 }
04165
04166 void NPC_PrintScore( gentity_t *ent )
04167 {
04168 Com_Printf( "%s: %d\n", ent->targetname, ent->client->ps.persistant[PERS_SCORE] );
04169 }
04170
04171
04172
04173
04174
04175
04176 qboolean showBBoxes = qfalse;
04177 void Cmd_NPC_f( gentity_t *ent )
04178 {
04179 char cmd[1024];
04180
04181 trap_Argv( 1, cmd, 1024 );
04182
04183 if ( !cmd[0] )
04184 {
04185 Com_Printf( "Valid NPC commands are:\n" );
04186 Com_Printf( " spawn [NPC type (from NCPCs.cfg)]\n" );
04187 Com_Printf( " kill [NPC targetname] or [all(kills all NPCs)] or 'team [teamname]'\n" );
04188 Com_Printf( " showbounds (draws exact bounding boxes of NPCs)\n" );
04189 Com_Printf( " score [NPC targetname] (prints number of kills per NPC)\n" );
04190 }
04191 else if ( Q_stricmp( cmd, "spawn" ) == 0 )
04192 {
04193 NPC_Spawn_f( ent );
04194 }
04195 else if ( Q_stricmp( cmd, "kill" ) == 0 )
04196 {
04197 NPC_Kill_f();
04198 }
04199 else if ( Q_stricmp( cmd, "showbounds" ) == 0 )
04200 {
04201 showBBoxes = showBBoxes ? qfalse : qtrue;
04202 }
04203 else if ( Q_stricmp ( cmd, "score" ) == 0 )
04204 {
04205 char cmd2[1024];
04206 gentity_t *ent = NULL;
04207
04208 trap_Argv(2, cmd2, 1024);
04209
04210 if ( !cmd2[0] )
04211 {
04212 int i;
04213
04214 Com_Printf( "SCORE LIST:\n" );
04215 for ( i = 0; i < ENTITYNUM_WORLD; i++ )
04216 {
04217 ent = &g_entities[i];
04218 if ( !ent || !ent->client )
04219 {
04220 continue;
04221 }
04222 NPC_PrintScore( ent );
04223 }
04224 }
04225 else
04226 {
04227 if ( (ent = G_Find( NULL, FOFS(targetname), cmd2 )) != NULL && ent->client )
04228 {
04229 NPC_PrintScore( ent );
04230 }
04231 else
04232 {
04233 Com_Printf( "ERROR: NPC score - no such NPC %s\n", cmd2 );
04234 }
04235 }
04236 }
04237 }