codemp/game/NPC_AI_Interrogator.c File Reference

#include "b_local.h"
#include "g_nav.h"

Go to the source code of this file.

Defines

#define VELOCITY_DECAY   0.85f
#define HUNTER_UPWARD_PUSH   2
#define HUNTER_STRAFE_VEL   32
#define HUNTER_STRAFE_DIS   200
#define HUNTER_FORWARD_BASE_SPEED   10
#define HUNTER_FORWARD_MULTIPLIER   2
#define MIN_DISTANCE   64

Enumerations

enum  { LSTATE_BLADESTOP = 0, LSTATE_BLADEUP, LSTATE_BLADEDOWN }

Functions

void Interrogator_Idle (void)
void DeathFX (gentity_t *ent)
void G_SoundOnEnt (gentity_t *ent, soundChannel_t channel, const char *soundPath)
void NPC_Interrogator_Precache (gentity_t *self)
void Interrogator_die (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod, int dFlags, int hitLoc)
void Interrogator_PartsMove (void)
void Interrogator_MaintainHeight (void)
void Interrogator_Strafe (void)
void Interrogator_Hunt (qboolean visible, qboolean advance)
void Interrogator_Melee (qboolean visible, qboolean advance)
void Interrogator_Attack (void)
void NPC_BSInterrogator_Default (void)


Define Documentation

#define HUNTER_FORWARD_BASE_SPEED   10
 

Definition at line 287 of file NPC_AI_Interrogator.c.

#define HUNTER_FORWARD_MULTIPLIER   2
 

Definition at line 288 of file NPC_AI_Interrogator.c.

#define HUNTER_STRAFE_DIS   200
 

Definition at line 232 of file NPC_AI_Interrogator.c.

#define HUNTER_STRAFE_VEL   32
 

Definition at line 231 of file NPC_AI_Interrogator.c.

#define HUNTER_UPWARD_PUSH   2
 

Definition at line 130 of file NPC_AI_Interrogator.c.

#define MIN_DISTANCE   64
 

Definition at line 338 of file NPC_AI_Interrogator.c.

#define VELOCITY_DECAY   0.85f
 

Definition at line 129 of file NPC_AI_Interrogator.c.


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
LSTATE_BLADESTOP 
LSTATE_BLADEUP 
LSTATE_BLADEDOWN 

Definition at line 8 of file NPC_AI_Interrogator.c.

00009 {
00010 LSTATE_BLADESTOP=0,
00011 LSTATE_BLADEUP,
00012 LSTATE_BLADEDOWN,
00013 };


Function Documentation

void DeathFX gentity_t ent  ) 
 

Definition at line 1882 of file g_combat.c.

01883 {
01884         vec3_t          effectPos, right;
01885         vec3_t          defaultDir;
01886 
01887         if ( !ent || !ent->client )
01888                 return;
01889 
01890         VectorSet(defaultDir, 0, 0, 1);
01891 
01892         // team no longer indicates species/race.  NPC_class should be used to identify certain npc types
01893         switch(ent->client->NPC_class)
01894         {
01895         case CLASS_MOUSE:
01896                 VectorCopy( ent->r.currentOrigin, effectPos );
01897                 effectPos[2] -= 20;
01898                 G_PlayEffectID( G_EffectIndex("env/small_explode"), effectPos, defaultDir );
01899                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mouse/misc/death1") );
01900                 break;
01901 
01902         case CLASS_PROBE:
01903                 VectorCopy( ent->r.currentOrigin, effectPos );
01904                 effectPos[2] += 50;
01905                 G_PlayEffectID( G_EffectIndex("explosions/probeexplosion1"), effectPos, defaultDir );
01906                 break;
01907                 
01908         case CLASS_ATST: 
01909                 AngleVectors( ent->r.currentAngles, NULL, right, NULL );
01910                 VectorMA( ent->r.currentOrigin, 20, right, effectPos );
01911                 effectPos[2] += 180;
01912                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01913                 VectorMA( effectPos, -40, right, effectPos );
01914                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01915                 break;
01916 
01917         case CLASS_SEEKER:
01918         case CLASS_REMOTE:
01919                 G_PlayEffectID( G_EffectIndex("env/small_explode"), ent->r.currentOrigin, defaultDir );
01920                 break;
01921 
01922         case CLASS_GONK:
01923                 VectorCopy( ent->r.currentOrigin, effectPos );
01924                 effectPos[2] -= 5;
01925 //              statusTextIndex = Q_irand( IGT_RESISTANCEISFUTILE, IGT_NAMEIS8OF12 );
01926                 G_Sound( ent, CHAN_AUTO, G_SoundIndex(va("sound/chars/gonk/misc/death%d.wav",Q_irand( 1, 3 ))) );
01927                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01928                 break;
01929 
01930         // should list all remaining droids here, hope I didn't miss any
01931         case CLASS_R2D2:
01932                 VectorCopy( ent->r.currentOrigin, effectPos );
01933                 effectPos[2] -= 10;
01934                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01935                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01936                 break;
01937 
01938         case CLASS_PROTOCOL: //c3p0
01939         case CLASS_R5D2:
01940                 VectorCopy( ent->r.currentOrigin, effectPos );
01941                 effectPos[2] -= 10;
01942                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01943                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01944                 break;
01945 
01946         case CLASS_MARK2:
01947                 VectorCopy( ent->r.currentOrigin, effectPos );
01948                 effectPos[2] -= 15;
01949                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01950                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_explo") );
01951                 break;
01952 
01953         case CLASS_INTERROGATOR:
01954                 VectorCopy( ent->r.currentOrigin, effectPos );
01955                 effectPos[2] -= 15;
01956                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01957                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/interrogator/misc/int_droid_explo") );
01958                 break;
01959 
01960         case CLASS_MARK1:
01961                 AngleVectors( ent->r.currentAngles, NULL, right, NULL );
01962                 VectorMA( ent->r.currentOrigin, 10, right, effectPos );
01963                 effectPos[2] -= 15;
01964                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01965                 VectorMA( effectPos, -20, right, effectPos );
01966                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01967                 VectorMA( effectPos, -20, right, effectPos );
01968                 G_PlayEffectID( G_EffectIndex("explosions/droidexplosion1"), effectPos, defaultDir );
01969                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/mark1/misc/mark1_explo") );
01970                 break;
01971 
01972         case CLASS_SENTRY:
01973                 G_Sound( ent, CHAN_AUTO, G_SoundIndex("sound/chars/sentry/misc/sentry_explo") );
01974                 VectorCopy( ent->r.currentOrigin, effectPos );
01975                 G_PlayEffectID( G_EffectIndex("env/med_explode"), effectPos, defaultDir );
01976                 break;
01977 
01978         default:
01979                 break;
01980 
01981         }
01982 
01983 }

void G_SoundOnEnt gentity_t ent,
soundChannel_t  channel,
const char *  soundPath
 

void Interrogator_Attack void   ) 
 

Definition at line 381 of file NPC_AI_Interrogator.c.

References CHAN_AUTO, entityShared_t::currentOrigin, DistanceHorizontalSquared(), gentity_s::enemy, G_SoundOnEnt(), Interrogator_Hunt(), Interrogator_Idle(), Interrogator_MaintainHeight(), Interrogator_Melee(), MIN_DISTANCE, NPC, NPC_CheckEnemyExt(), NPC_ClearLOS4(), NPC_FaceEnemy(), NPCInfo, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, SCF_CHASE_ENEMIES, gNPC_t::scriptFlags, TIMER_Done(), TIMER_Set(), and va().

Referenced by NPC_BSInterrogator_Default().

00382 {
00383         float           distance;       
00384         qboolean        visible;
00385         qboolean        advance;
00386 
00387         // Always keep a good height off the ground
00388         Interrogator_MaintainHeight();
00389 
00390         //randomly talk
00391         if ( TIMER_Done(NPC,"patrolNoise") )
00392         {
00393                 if (TIMER_Done(NPC,"angerNoise"))
00394                 {
00395                         G_SoundOnEnt( NPC, CHAN_AUTO, va("sound/chars/probe/misc/talk.wav",     Q_irand(1, 3)) );
00396 
00397                         TIMER_Set( NPC, "patrolNoise", Q_irand( 4000, 10000 ) );
00398                 }
00399         }
00400 
00401         // If we don't have an enemy, just idle
00402         if ( NPC_CheckEnemyExt(qfalse) == qfalse )
00403         {
00404                 Interrogator_Idle();
00405                 return;
00406         }
00407 
00408         // Rate our distance to the target, and our visibilty
00409         distance        = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); 
00410         visible         = NPC_ClearLOS4( NPC->enemy );
00411         advance         = (qboolean)(distance > MIN_DISTANCE*MIN_DISTANCE );
00412 
00413         if ( !visible )
00414         {
00415                 advance = qtrue;
00416         }
00417         if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES )
00418         {
00419                 Interrogator_Hunt( visible, advance );
00420         }
00421 
00422         NPC_FaceEnemy( qtrue );
00423 
00424         if (!advance)
00425         {
00426                 Interrogator_Melee( visible, advance );
00427         }
00428 }

void Interrogator_die gentity_t self,
gentity_t inflictor,
gentity_t attacker,
int  damage,
int  mod,
int  dFlags,
int  hitLoc
 

Definition at line 34 of file NPC_AI_Interrogator.c.

References gentity_s::client, EF2_FLYING, playerState_s::eFlags2, gentity_t, gclient_s::ps, Q_irand(), and playerState_s::velocity.

00035 {
00036         self->client->ps.velocity[2] = -100;
00037         /*
00038         self->locationDamage[HL_NONE] += damage;
00039         if (self->locationDamage[HL_NONE] > 40)
00040         {
00041                 DeathFX(self);
00042                 self->client->ps.eFlags |= EF_NODRAW;
00043                 self->contents = CONTENTS_CORPSE;
00044         }
00045         else
00046         */
00047         {
00048                 self->client->ps.eFlags2 &= ~EF2_FLYING;//moveType = MT_WALK;
00049                 self->client->ps.velocity[0] = Q_irand( -10, -20 );
00050                 self->client->ps.velocity[1] = Q_irand( -10, -20 );
00051                 self->client->ps.velocity[2] = -100;
00052         }
00053         //self->takedamage = qfalse;
00054         //self->client->ps.eFlags |= EF_NODRAW;
00055         //self->contents = 0;
00056         return;
00057 }

void Interrogator_Hunt qboolean  visible,
qboolean  advance
 

Definition at line 290 of file NPC_AI_Interrogator.c.

References gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, g_spskill, gNPC_t::goalEntity, gNPC_t::goalRadius, HUNTER_FORWARD_BASE_SPEED, HUNTER_FORWARD_MULTIPLIER, vmCvar_t::integer, Interrogator_PartsMove(), Interrogator_Strafe(), level, NPC, NPC_FaceEnemy(), NPC_GetMoveDirection(), NPCInfo, gclient_s::ps, qfalse, gentity_s::r, gNPC_t::standTime, level_locals_t::time, vec3_t, VectorMA, VectorNormalize(), VectorSubtract, and playerState_s::velocity.

Referenced by Interrogator_Attack(), and Interrogator_Melee().

00291 {
00292         float   distance, speed;
00293         vec3_t  forward;
00294 
00295         Interrogator_PartsMove();
00296 
00297         NPC_FaceEnemy(qfalse);
00298 
00299         //If we're not supposed to stand still, pursue the player
00300         if ( NPCInfo->standTime < level.time )
00301         {
00302                 // Only strafe when we can see the player
00303                 if ( visible )
00304                 {
00305                         Interrogator_Strafe();
00306                         if ( NPCInfo->standTime > level.time )
00307                         {//successfully strafed
00308                                 return;
00309                         }
00310                 }
00311         }
00312 
00313         //If we don't want to advance, stop here
00314         if ( advance == qfalse )
00315                 return;
00316 
00317         //Only try and navigate if the player is visible
00318         if ( visible == qfalse )
00319         {
00320                 // Move towards our goal
00321                 NPCInfo->goalEntity = NPC->enemy;
00322                 NPCInfo->goalRadius = 12;
00323 
00324                 //Get our direction from the navigator if we can't see our target
00325                 if ( NPC_GetMoveDirection( forward, &distance ) == qfalse )
00326                         return;
00327         }
00328         else
00329         {
00330                 VectorSubtract( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, forward );
00331                 distance = VectorNormalize( forward );
00332         }
00333 
00334         speed = HUNTER_FORWARD_BASE_SPEED + HUNTER_FORWARD_MULTIPLIER * g_spskill.integer;
00335         VectorMA( NPC->client->ps.velocity, speed, forward, NPC->client->ps.velocity );
00336 }

void Interrogator_Idle void   ) 
 

Definition at line 435 of file NPC_AI_Interrogator.c.

References CHAN_AUTO, G_SoundOnEnt(), Interrogator_MaintainHeight(), NPC, NPC_BSIdle(), NPC_CheckPlayerTeamStealth(), NPC_UpdateAngles(), and qtrue.

Referenced by Interrogator_Attack(), and NPC_BSInterrogator_Default().

00436 {
00437         if ( NPC_CheckPlayerTeamStealth() )
00438         {
00439                 G_SoundOnEnt( NPC, CHAN_AUTO, "sound/chars/mark1/misc/anger.wav" );
00440                 NPC_UpdateAngles( qtrue, qtrue );
00441                 return;
00442         }
00443 
00444         Interrogator_MaintainHeight();
00445 
00446         NPC_BSIdle();
00447 }

void Interrogator_MaintainHeight void   ) 
 

Definition at line 137 of file NPC_AI_Interrogator.c.

References gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, fabs(), G_SoundIndex(), gentity_t, gNPC_t::goalEntity, gNPC_t::lastGoalEntity, entityState_s::loopSound, entityShared_t::maxs, NPC, NPC_UpdateAngles(), NPCInfo, NULL, gclient_s::ps, qtrue, gentity_s::r, gentity_s::s, ucmd, usercmd_s::upmove, playerState_s::velocity, and VELOCITY_DECAY.

Referenced by Interrogator_Attack(), and Interrogator_Idle().

00138 {       
00139         float   dif;
00140 //      vec3_t  endPos;
00141 //      trace_t trace;
00142 
00143         NPC->s.loopSound = G_SoundIndex( "sound/chars/interrogator/misc/torture_droid_lp" );
00144         // Update our angles regardless
00145         NPC_UpdateAngles( qtrue, qtrue );
00146 
00147         // If we have an enemy, we should try to hover at about enemy eye level
00148         if ( NPC->enemy )
00149         {
00150                 // Find the height difference
00151                 dif = (NPC->enemy->r.currentOrigin[2] + NPC->enemy->r.maxs[2]) - NPC->r.currentOrigin[2]; 
00152 
00153                 // cap to prevent dramatic height shifts
00154                 if ( fabs( dif ) > 2 )
00155                 {
00156                         if ( fabs( dif ) > 16 )
00157                         {
00158                                 dif = ( dif < 0 ? -16 : 16 );
00159                         }
00160 
00161                         NPC->client->ps.velocity[2] = (NPC->client->ps.velocity[2]+dif)/2;
00162                 }
00163         }
00164         else
00165         {
00166                 gentity_t *goal = NULL;
00167 
00168                 if ( NPCInfo->goalEntity )      // Is there a goal?
00169                 {
00170                         goal = NPCInfo->goalEntity;
00171                 }
00172                 else
00173                 {
00174                         goal = NPCInfo->lastGoalEntity;
00175                 }
00176                 if ( goal )
00177                 {
00178                         dif = goal->r.currentOrigin[2] - NPC->r.currentOrigin[2];
00179 
00180                         if ( fabs( dif ) > 24 )
00181                         {
00182                                 ucmd.upmove = ( ucmd.upmove < 0 ? -4 : 4 );
00183                         }
00184                         else
00185                         {
00186                                 if ( NPC->client->ps.velocity[2] )
00187                                 {
00188                                         NPC->client->ps.velocity[2] *= VELOCITY_DECAY;
00189 
00190                                         if ( fabs( NPC->client->ps.velocity[2] ) < 2 )
00191                                         {
00192                                                 NPC->client->ps.velocity[2] = 0;
00193                                         }
00194                                 }
00195                         }
00196                 }
00197                 // Apply friction
00198                 else if ( NPC->client->ps.velocity[2] )
00199                 {
00200                         NPC->client->ps.velocity[2] *= VELOCITY_DECAY;
00201 
00202                         if ( fabs( NPC->client->ps.velocity[2] ) < 1 )
00203                         {
00204                                 NPC->client->ps.velocity[2] = 0;
00205                         }
00206                 }
00207         }
00208 
00209         // Apply friction
00210         if ( NPC->client->ps.velocity[0] )
00211         {
00212                 NPC->client->ps.velocity[0] *= VELOCITY_DECAY;
00213 
00214                 if ( fabs( NPC->client->ps.velocity[0] ) < 1 )
00215                 {
00216                         NPC->client->ps.velocity[0] = 0;
00217                 }
00218         }
00219 
00220         if ( NPC->client->ps.velocity[1] )
00221         {
00222                 NPC->client->ps.velocity[1] *= VELOCITY_DECAY;
00223 
00224                 if ( fabs( NPC->client->ps.velocity[1] ) < 1 )
00225                 {
00226                         NPC->client->ps.velocity[1] = 0;
00227                 }
00228         }
00229 }

void Interrogator_Melee qboolean  visible,
qboolean  advance
 

Definition at line 345 of file NPC_AI_Interrogator.c.

References CHAN_AUTO, entityShared_t::currentOrigin, DAMAGE_NO_KNOCKBACK, gentity_s::enemy, G_Damage(), G_Sound(), G_SoundIndex(), Interrogator_Hunt(), entityShared_t::maxs, entityShared_t::mins, MOD_MELEE, NPC, NPCInfo, Q_irand(), gentity_s::r, SCF_CHASE_ENEMIES, gNPC_t::scriptFlags, TIMER_Done(), and TIMER_Set().

Referenced by Interrogator_Attack().

00346 {
00347         if ( TIMER_Done( NPC, "attackDelay" ) ) // Attack?
00348         {
00349                 // Make sure that we are within the height range before we allow any damage to happen
00350                 if ( NPC->r.currentOrigin[2] >= NPC->enemy->r.currentOrigin[2]+NPC->enemy->r.mins[2] && NPC->r.currentOrigin[2]+NPC->r.mins[2]+8 < NPC->enemy->r.currentOrigin[2]+NPC->enemy->r.maxs[2] )
00351                 {
00352                         //gentity_t *tent;
00353 
00354                         TIMER_Set( NPC, "attackDelay", Q_irand( 500, 3000 ) );
00355                         G_Damage( NPC->enemy, NPC, NPC, 0, 0, 2, DAMAGE_NO_KNOCKBACK, MOD_MELEE );
00356 
00357                 //      NPC->enemy->client->poisonDamage = 18;
00358                 //      NPC->enemy->client->poisonTime = level.time + 1000;
00359 
00360                         // Drug our enemy up and do the wonky vision thing
00361 //                      tent = G_TempEntity( NPC->enemy->r.currentOrigin, EV_DRUGGED );
00362 //                      tent->owner = NPC->enemy;
00363 
00364                         //rwwFIXMEFIXME: poison damage
00365 
00366                         G_Sound( NPC, CHAN_AUTO, G_SoundIndex( "sound/chars/interrogator/misc/torture_droid_inject.mp3" ));
00367                 }
00368         }
00369 
00370         if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES )
00371         {
00372                 Interrogator_Hunt( visible, advance );
00373         }
00374 }

void Interrogator_PartsMove void   ) 
 

Definition at line 64 of file NPC_AI_Interrogator.c.

References AngleNormalize360(), gNPC_t::localState, LSTATE_BLADEDOWN, LSTATE_BLADEUP, NPC, NPC_SetBoneAngles(), NPCInfo, gentity_s::pos1, gentity_s::pos2, gentity_s::pos3, Q_irand(), TIMER_Done(), and TIMER_Set().

Referenced by Interrogator_Hunt().

00065 {
00066         // Syringe
00067         if ( TIMER_Done(NPC,"syringeDelay") )
00068         {
00069                 NPC->pos1[1] = AngleNormalize360( NPC->pos1[1]);
00070 
00071                 if ((NPC->pos1[1] < 60) || (NPC->pos1[1] > 300))
00072                 {
00073                         NPC->pos1[1]+=Q_irand( -20, 20 );       // Pitch        
00074                 }
00075                 else if (NPC->pos1[1] > 180)
00076                 {
00077                         NPC->pos1[1]=Q_irand( 300, 360 );       // Pitch        
00078                 }
00079                 else 
00080                 {
00081                         NPC->pos1[1]=Q_irand( 0, 60 );  // Pitch        
00082                 }
00083 
00084         //      gi.G2API_SetBoneAnglesIndex( &NPC->ghoul2[NPC->playerModel], NPC->genericBone1, NPC->pos1, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL ); 
00085                 NPC_SetBoneAngles(NPC, "left_arm", NPC->pos1);
00086 
00087                 TIMER_Set( NPC, "syringeDelay", Q_irand( 100, 1000 ) );
00088         }
00089 
00090         // Scalpel
00091         if ( TIMER_Done(NPC,"scalpelDelay") )
00092         {
00093                 // Change pitch
00094                 if ( NPCInfo->localState == LSTATE_BLADEDOWN )  // Blade is moving down
00095                 {
00096                         NPC->pos2[0]-= 30;
00097                         if (NPC->pos2[0] < 180)
00098                         {
00099                                 NPC->pos2[0] = 180;
00100                                 NPCInfo->localState = LSTATE_BLADEUP;   // Make it move up
00101                         }
00102                 }
00103                 else                                                                                    // Blade is coming back up
00104                 {
00105                         NPC->pos2[0]+= 30;
00106                         if (NPC->pos2[0] >= 360)
00107                         {
00108                                 NPC->pos2[0] = 360;
00109                                 NPCInfo->localState = LSTATE_BLADEDOWN; // Make it move down
00110                                 TIMER_Set( NPC, "scalpelDelay", Q_irand( 100, 1000 ) );
00111                         }
00112                 }
00113 
00114                 NPC->pos2[0] = AngleNormalize360( NPC->pos2[0]);
00115         //      gi.G2API_SetBoneAnglesIndex( &NPC->ghoul2[NPC->playerModel], NPC->genericBone2, NPC->pos2, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL ); 
00116 
00117                 NPC_SetBoneAngles(NPC, "right_arm", NPC->pos2);
00118         }
00119 
00120         // Claw
00121         NPC->pos3[1] += Q_irand( 10, 30 );
00122         NPC->pos3[1] = AngleNormalize360( NPC->pos3[1]);
00123         //gi.G2API_SetBoneAnglesIndex( &NPC->ghoul2[NPC->playerModel], NPC->genericBone3, NPC->pos3, BONE_ANGLES_POSTMULT, POSITIVE_X, NEGATIVE_Y, NEGATIVE_Z, NULL ); 
00124 
00125         NPC_SetBoneAngles(NPC, "claw", NPC->pos3);
00126 
00127 }

void Interrogator_Strafe void   ) 
 

Definition at line 238 of file NPC_AI_Interrogator.c.

References AngleVectors(), gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, renderInfo_s::eyeAngles, fabs(), trace_t::fraction, HUNTER_STRAFE_DIS, HUNTER_STRAFE_VEL, HUNTER_UPWARD_PUSH, level, MASK_SOLID, NPC, NPCInfo, NULL, entityState_s::number, gclient_s::ps, gentity_s::r, rand(), random, gclient_s::renderInfo, gentity_s::s, gNPC_t::standTime, level_locals_t::time, trap_Trace(), vec3_t, VectorMA, and playerState_s::velocity.

Referenced by Interrogator_Hunt().

00239 {
00240         int             dir;
00241         vec3_t  end, right;
00242         trace_t tr;
00243         float   dif;
00244 
00245         AngleVectors( NPC->client->renderInfo.eyeAngles, NULL, right, NULL );
00246 
00247         // Pick a random strafe direction, then check to see if doing a strafe would be
00248         //      reasonable valid
00249         dir = ( rand() & 1 ) ? -1 : 1;
00250         VectorMA( NPC->r.currentOrigin, HUNTER_STRAFE_DIS * dir, right, end );
00251 
00252         trap_Trace( &tr, NPC->r.currentOrigin, NULL, NULL, end, NPC->s.number, MASK_SOLID );
00253 
00254         // Close enough
00255         if ( tr.fraction > 0.9f )
00256         {
00257                 VectorMA( NPC->client->ps.velocity, HUNTER_STRAFE_VEL * dir, right, NPC->client->ps.velocity );
00258 
00259                 // Add a slight upward push
00260                 if ( NPC->enemy )
00261                 {
00262                         // Find the height difference
00263                         dif = (NPC->enemy->r.currentOrigin[2] + 32) - NPC->r.currentOrigin[2]; 
00264 
00265                         // cap to prevent dramatic height shifts
00266                         if ( fabs( dif ) > 8 )
00267                         {
00268                                 dif = ( dif < 0 ? -HUNTER_UPWARD_PUSH : HUNTER_UPWARD_PUSH );
00269                         }
00270 
00271                         NPC->client->ps.velocity[2] += dif;
00272 
00273                 }
00274 
00275                 // Set the strafe start time 
00276                 //NPC->fx_time = level.time;
00277                 NPCInfo->standTime = level.time + 3000 + random() * 500;
00278         }
00279 }

void NPC_BSInterrogator_Default void   ) 
 

Definition at line 454 of file NPC_AI_Interrogator.c.

References gentity_s::enemy, Interrogator_Attack(), Interrogator_Idle(), and NPC.

Referenced by NPC_BehaviorSet_Interrogator().

00455 {
00456         //NPC->e_DieFunc = dieF_Interrogator_die;
00457 
00458         if ( NPC->enemy )
00459         {
00460                 Interrogator_Attack();
00461         }
00462         else
00463         {
00464                 Interrogator_Idle();
00465         }
00466 
00467 }

void NPC_Interrogator_Precache gentity_t self  ) 
 

Definition at line 20 of file NPC_AI_Interrogator.c.

References G_EffectIndex(), G_SoundIndex(), and gentity_t.

Referenced by NPC_SpawnType(), and SP_NPC_Droid_Interrogator().

00021 {
00022         G_SoundIndex( "sound/chars/interrogator/misc/torture_droid_lp" );
00023         G_SoundIndex("sound/chars/mark1/misc/anger.wav");
00024         G_SoundIndex( "sound/chars/probe/misc/talk");
00025         G_SoundIndex( "sound/chars/interrogator/misc/torture_droid_inject" );
00026         G_SoundIndex( "sound/chars/interrogator/misc/int_droid_explo" );
00027         G_EffectIndex( "explosions/droidexplosion1" );
00028 }