codemp/game/NPC_AI_Mark2.c File Reference

#include "b_local.h"
#include "g_nav.h"
#include "../namespace_begin.h"
#include "../namespace_end.h"

Go to the source code of this file.

Defines

#define AMMO_POD_HEALTH   1
#define TURN_OFF   0x00000100
#define VELOCITY_DECAY   0.25
#define MAX_DISTANCE   256
#define MAX_DISTANCE_SQR   ( MAX_DISTANCE * MAX_DISTANCE )
#define MIN_DISTANCE   24
#define MIN_DISTANCE_SQR   ( MIN_DISTANCE * MIN_DISTANCE )

Enumerations

enum  { LSTATE_NONE = 0, LSTATE_DROPPINGDOWN, LSTATE_DOWN, LSTATE_RISINGUP }

Functions

gitem_tBG_FindItemForAmmo (ammo_t ammo)
void NPC_Mark2_Precache (void)
void NPC_Mark2_Part_Explode (gentity_t *self, int bolt)
void NPC_Mark2_Pain (gentity_t *self, gentity_t *attacker, int damage)
void Mark2_Hunt (void)
void Mark2_FireBlaster (qboolean advance)
void Mark2_BlasterAttack (qboolean advance)
void Mark2_AttackDecision (void)
void Mark2_Patrol (void)
void Mark2_Idle (void)
void NPC_BSMark2_Default (void)


Define Documentation

#define AMMO_POD_HEALTH   1
 

Definition at line 5 of file NPC_AI_Mark2.c.

#define MAX_DISTANCE   256
 

Definition at line 9 of file NPC_AI_Mark2.c.

#define MAX_DISTANCE_SQR   ( MAX_DISTANCE * MAX_DISTANCE )
 

Definition at line 10 of file NPC_AI_Mark2.c.

#define MIN_DISTANCE   24
 

Definition at line 11 of file NPC_AI_Mark2.c.

#define MIN_DISTANCE_SQR   ( MIN_DISTANCE * MIN_DISTANCE )
 

Definition at line 12 of file NPC_AI_Mark2.c.

#define TURN_OFF   0x00000100
 

Definition at line 6 of file NPC_AI_Mark2.c.

#define VELOCITY_DECAY   0.25
 

Definition at line 8 of file NPC_AI_Mark2.c.


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
LSTATE_NONE 
LSTATE_DROPPINGDOWN 
LSTATE_DOWN 
LSTATE_RISINGUP 

Definition at line 19 of file NPC_AI_Mark2.c.

00020 {
00021         LSTATE_NONE = 0,
00022         LSTATE_DROPPINGDOWN,
00023         LSTATE_DOWN,
00024         LSTATE_RISINGUP,
00025 };


Function Documentation

gitem_t* BG_FindItemForAmmo ammo_t  ammo  ) 
 

Definition at line 1941 of file bg_misc.c.

01941                                            {
01942         gitem_t *it;
01943         
01944         for ( it = bg_itemlist + 1 ; it->classname ; it++) {
01945                 if ( it->giType == IT_AMMO && it->giTag == ammo ) {
01946                         return it;
01947                 }
01948         }
01949 
01950         Com_Error( ERR_DROP, "Couldn't find item for ammo %i", ammo);
01951         return NULL;
01952 }

void Mark2_AttackDecision void   ) 
 

Definition at line 212 of file NPC_AI_Mark2.c.

References BOTH_RUN1START, BOTH_RUN1STOP, gentity_s::client, entityShared_t::currentOrigin, DistanceHorizontalSquared(), gentity_s::enemy, FL_SHIELDED, gentity_s::flags, playerState_s::legsTimer, gNPC_t::localState, LSTATE_DOWN, LSTATE_DROPPINGDOWN, LSTATE_NONE, LSTATE_RISINGUP, Mark2_BlasterAttack(), Mark2_Hunt(), MIN_DISTANCE_SQR, NPC, NPC_ClearLOS4(), NPC_FaceEnemy(), NPC_SetAnim(), NPCInfo, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, TIMER_Done(), TIMER_Set(), and playerState_s::torsoAnim.

Referenced by NPC_BSMark2_Default().

00213 {
00214         float           distance;
00215         qboolean        visible;
00216         qboolean        advance;
00217 
00218         NPC_FaceEnemy( qtrue );
00219 
00220         distance        = (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ); 
00221         visible         = NPC_ClearLOS4( NPC->enemy );
00222         advance         = (qboolean)(distance > MIN_DISTANCE_SQR);
00223 
00224         // He's been ordered to get up
00225         if (NPCInfo->localState == LSTATE_RISINGUP)
00226         {
00227                 NPC->flags &= ~FL_SHIELDED;
00228                 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1START, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
00229                 if ((NPC->client->ps.legsTimer<=0) && 
00230                         NPC->client->ps.torsoAnim == BOTH_RUN1START )
00231                 {
00232                         NPCInfo->localState = LSTATE_NONE;      // He's up again.
00233                 }
00234                 return;
00235         }
00236 
00237         // If we cannot see our target, move to see it
00238         if ((!visible) || (!NPC_FaceEnemy(qtrue)))
00239         {
00240                 // If he's going down or is down, make him get up
00241                 if ((NPCInfo->localState == LSTATE_DOWN) || (NPCInfo->localState == LSTATE_DROPPINGDOWN))
00242                 {
00243                         if ( TIMER_Done( NPC, "downTime" ) )    // Down being down?? (The delay is so he doesn't pop up and down when the player goes in and out of range)
00244                         {
00245                                 NPCInfo->localState = LSTATE_RISINGUP;
00246                                 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
00247                                 TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) );      // So he runs for a while before testing to see if he should drop down.
00248                         }
00249                 }
00250                 else
00251                 {
00252                         Mark2_Hunt();
00253                 }
00254                 return;
00255         }
00256 
00257         // He's down but he could advance if he wants to.
00258         if ((advance) && (TIMER_Done( NPC, "downTime" )) && (NPCInfo->localState == LSTATE_DOWN))
00259         {
00260                 NPCInfo->localState = LSTATE_RISINGUP;
00261                 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
00262                 TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) );      // So he runs for a while before testing to see if he should drop down.
00263         }
00264 
00265         NPC_FaceEnemy( qtrue );
00266 
00267         // Dropping down to shoot
00268         if (NPCInfo->localState == LSTATE_DROPPINGDOWN)
00269         {
00270                 NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
00271                 TIMER_Set( NPC, "downTime", Q_irand( 3000, 9000) );
00272 
00273                 if ((NPC->client->ps.legsTimer<=0) && NPC->client->ps.torsoAnim == BOTH_RUN1STOP )
00274                 {
00275                         NPC->flags |= FL_SHIELDED;
00276                         NPCInfo->localState = LSTATE_DOWN;
00277                 }
00278         }
00279         // He's down and shooting
00280         else if (NPCInfo->localState == LSTATE_DOWN)
00281         {
00282                 NPC->flags |= FL_SHIELDED;//only damagable by lightsabers and missiles
00283 
00284                 Mark2_BlasterAttack(qfalse);
00285         }
00286         else if (TIMER_Done( NPC, "runTime" ))  // Lowering down to attack. But only if he's done running at you.
00287         {
00288                 NPCInfo->localState = LSTATE_DROPPINGDOWN;
00289         }
00290         else if (advance)
00291         {
00292                 // We can see enemy so shoot him if timer lets you.
00293                 Mark2_BlasterAttack(advance);
00294         }
00295 }

void Mark2_BlasterAttack qboolean  advance  ) 
 

Definition at line 186 of file NPC_AI_Mark2.c.

References gNPC_t::localState, LSTATE_NONE, Mark2_FireBlaster(), Mark2_Hunt(), NPC, NPCInfo, Q_irand(), TIMER_Done(), and TIMER_Set().

Referenced by Mark2_AttackDecision().

00187 {
00188         if ( TIMER_Done( NPC, "attackDelay" ) ) // Attack?
00189         {
00190                 if (NPCInfo->localState == LSTATE_NONE) // He's up so shoot less often.
00191                 {
00192                         TIMER_Set( NPC, "attackDelay", Q_irand( 500, 2000) );
00193                 }
00194                 else
00195                 {
00196                         TIMER_Set( NPC, "attackDelay", Q_irand( 100, 500) );
00197                 }
00198                 Mark2_FireBlaster(advance);
00199                 return;
00200         }
00201         else if (advance)
00202         {
00203                 Mark2_Hunt();
00204         }
00205 }

void Mark2_FireBlaster qboolean  advance  ) 
 

Definition at line 137 of file NPC_AI_Mark2.c.

References AngleVectors(), CalcEntitySpot(), CHAN_AUTO, gentity_s::classname, gentity_s::clipmask, CONTENTS_LIGHTSABER, CreateMissile(), entityShared_t::currentAngles, entityShared_t::currentOrigin, gentity_s::damage, DAMAGE_DEATH_KNOCKBACK, gentity_s::dflags, gentity_s::enemy, G_EffectIndex(), G_PlayEffectID(), G_Sound(), G_SoundIndex(), gentity_t, gentity_s::ghoul2, gentity_s::health, level, MASK_SHOT, gentity_s::methodOfDeath, MOD_BRYAR_PISTOL, gentity_s::modelScale, NPC, NULL, ORIGIN, qfalse, gentity_s::r, gentity_s::s, SPOT_HEAD, level_locals_t::time, trap_G2API_AddBolt(), trap_G2API_GetBoltMatrix(), vec3_t, vectoangles(), VectorSubtract, entityState_s::weapon, and WP_BRYAR_PISTOL.

Referenced by Mark2_BlasterAttack().

00138 {
00139         vec3_t  muzzle1,enemy_org1,delta1,angleToEnemy1;
00140         static  vec3_t  forward, vright, up;
00141         static  vec3_t  muzzle;
00142         gentity_t       *missile;
00143         mdxaBone_t      boltMatrix;
00144         int bolt = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash");
00145 
00146         trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, 
00147                                 bolt,
00148                                 &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time,
00149                                 NULL, NPC->modelScale );
00150 
00151         BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 );
00152 
00153         if (NPC->health)
00154         {
00155                 CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org1 );
00156                 VectorSubtract (enemy_org1, muzzle1, delta1);
00157                 vectoangles ( delta1, angleToEnemy1 );
00158                 AngleVectors (angleToEnemy1, forward, vright, up);
00159         }
00160         else
00161         {
00162                 AngleVectors (NPC->r.currentAngles, forward, vright, up);
00163         }
00164 
00165         G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle1, forward );
00166 
00167         G_Sound( NPC, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_fire"));
00168 
00169         missile = CreateMissile( muzzle1, forward, 1600, 10000, NPC, qfalse );
00170 
00171         missile->classname = "bryar_proj";
00172         missile->s.weapon = WP_BRYAR_PISTOL;
00173 
00174         missile->damage = 1;
00175         missile->dflags = DAMAGE_DEATH_KNOCKBACK;
00176         missile->methodOfDeath = MOD_BRYAR_PISTOL;
00177         missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
00178 
00179 }

void Mark2_Hunt void   ) 
 

Definition at line 118 of file NPC_AI_Mark2.c.

References gNPC_t::combatMove, gentity_s::enemy, gNPC_t::goalEntity, NPC, NPC_FaceEnemy(), NPC_MoveToGoal(), NPCInfo, NULL, and qtrue.

Referenced by Mark2_AttackDecision(), and Mark2_BlasterAttack().

00119 {
00120         if ( NPCInfo->goalEntity == NULL )
00121         {
00122                 NPCInfo->goalEntity = NPC->enemy;
00123         }
00124 
00125         // Turn toward him before moving towards him.
00126         NPC_FaceEnemy( qtrue );
00127 
00128         NPCInfo->combatMove = qtrue;
00129         NPC_MoveToGoal( qtrue );
00130 }

void Mark2_Idle void   ) 
 

Definition at line 337 of file NPC_AI_Mark2.c.

References NPC_BSIdle().

Referenced by NPC_BSMark2_Default().

00338 {
00339         NPC_BSIdle();
00340 }

void Mark2_Patrol void   ) 
 

Definition at line 303 of file NPC_AI_Mark2.c.

References BUTTON_WALKING, usercmd_s::buttons, gentity_s::enemy, NPC, NPC_CheckPlayerTeamStealth(), NPC_MoveToGoal(), NPC_UpdateAngles(), Q_irand(), qtrue, TIMER_Done(), TIMER_Set(), ucmd, and UpdateGoal().

Referenced by NPC_BSMark2_Default().

00304 {
00305         if ( NPC_CheckPlayerTeamStealth() )
00306         {
00307 //              G_Sound( NPC, G_SoundIndex("sound/chars/mark1/misc/anger.wav"));
00308                 NPC_UpdateAngles( qtrue, qtrue );
00309                 return;
00310         }
00311 
00312         //If we have somewhere to go, then do that
00313         if (!NPC->enemy)
00314         {
00315                 if ( UpdateGoal() )
00316                 {
00317                         ucmd.buttons |= BUTTON_WALKING;
00318                         NPC_MoveToGoal( qtrue );
00319                         NPC_UpdateAngles( qtrue, qtrue );
00320                 }
00321 
00322                 //randomly talk
00323                 if (TIMER_Done(NPC,"patrolNoise"))
00324                 {
00325 //                      G_Sound( NPC, G_SoundIndex(va("sound/chars/mark1/misc/talk%d.wav",      Q_irand(1, 4))));
00326 
00327                         TIMER_Set( NPC, "patrolNoise", Q_irand( 2000, 4000 ) );
00328                 }
00329         }
00330 }

void NPC_BSMark2_Default void   ) 
 

Definition at line 347 of file NPC_AI_Mark2.c.

References gentity_s::enemy, gNPC_t::goalEntity, Mark2_AttackDecision(), Mark2_Idle(), Mark2_Patrol(), NPC, NPCInfo, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_Mark2().

00348 {
00349         if ( NPC->enemy )
00350         {
00351                 NPCInfo->goalEntity = NPC->enemy;
00352                 Mark2_AttackDecision();
00353         }
00354         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00355         {
00356                 Mark2_Patrol();
00357         }
00358         else
00359         {
00360                 Mark2_Idle();
00361         }
00362 }

void NPC_Mark2_Pain gentity_t self,
gentity_t attacker,
int  damage
 

Definition at line 80 of file NPC_AI_Mark2.c.

References AMMO_POD_HEALTH, CHAN_AUTO, gentity_s::count, DAMAGE_NO_PROTECTION, G_Damage(), G_Sound(), G_SoundIndex(), gentity_t, gentity_s::ghoul2, gPainHitLoc, gentity_s::health, HL_GENERIC1, gentity_s::locationDamage, MOD_UNKNOWN, NPC_Mark2_Part_Explode(), NPC_Pain(), NPC_SetSurfaceOnOff(), NULL, trap_G2API_AddBolt(), TURN_OFF, and va().

Referenced by NPC_PainFunc().

00081 {
00082         int newBolt,i;
00083         int hitLoc = gPainHitLoc;
00084         
00085         NPC_Pain( self, attacker, damage );
00086 
00087         for (i=0;i<3;i++)
00088         {
00089                 if ((hitLoc==HL_GENERIC1+i) && (self->locationDamage[HL_GENERIC1+i] > AMMO_POD_HEALTH)) // Blow it up?
00090                 {
00091                         if (self->locationDamage[hitLoc] >= AMMO_POD_HEALTH)
00092                         {                       
00093                                 newBolt = trap_G2API_AddBolt( self->ghoul2, 0, va("torso_canister%d",(i+1)) );
00094                                 if ( newBolt != -1 )
00095                                 {
00096                                         NPC_Mark2_Part_Explode(self,newBolt);
00097                                 }
00098                                 NPC_SetSurfaceOnOff( self, va("torso_canister%d",(i+1)), TURN_OFF );
00099                                 break;
00100                         }
00101                 }
00102         }
00103 
00104         G_Sound( self, CHAN_AUTO, G_SoundIndex( "sound/chars/mark2/misc/mark2_pain" ));
00105 
00106         // If any pods were blown off, kill him
00107         if (self->count > 0)
00108         {
00109                 G_Damage( self, NULL, NULL, NULL, NULL, self->health, DAMAGE_NO_PROTECTION, MOD_UNKNOWN );
00110         }
00111 }

void NPC_Mark2_Part_Explode gentity_t self,
int  bolt
 

Definition at line 50 of file NPC_AI_Mark2.c.

References gentity_s::count, entityShared_t::currentAngles, entityShared_t::currentOrigin, G_EffectIndex(), G_PlayEffectID(), gentity_t, gentity_s::ghoul2, level, gentity_s::modelScale, NEGATIVE_Y, NULL, ORIGIN, gentity_s::r, level_locals_t::time, trap_G2API_GetBoltMatrix(), and vec3_t.

Referenced by NPC_Mark2_Pain().

00051 {
00052         if ( bolt >=0 )
00053         {
00054                 mdxaBone_t      boltMatrix;
00055                 vec3_t          org, dir;
00056 
00057                 trap_G2API_GetBoltMatrix( self->ghoul2, 0, 
00058                                         bolt,
00059                                         &boltMatrix, self->r.currentAngles, self->r.currentOrigin, level.time,
00060                                         NULL, self->modelScale );
00061 
00062                 BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org );
00063                 BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, dir );
00064 
00065                 G_PlayEffectID( G_EffectIndex("env/med_explode2"), org, dir );
00066                 G_PlayEffectID( G_EffectIndex("blaster/smoke_bolton"), org, dir );
00067         }
00068 
00069         //G_PlayEffectID( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, bolt, self->s.number);
00070 
00071         self->count++;  // Count of pods blown off
00072 }

void NPC_Mark2_Precache void   ) 
 

Definition at line 27 of file NPC_AI_Mark2.c.

References AMMO_BLASTER, AMMO_METAL_BOLTS, AMMO_POWERCELL, BG_FindItemForAmmo(), BG_FindItemForWeapon(), G_EffectIndex(), G_SoundIndex(), RegisterItem(), and WP_BRYAR_PISTOL.

Referenced by NPC_SpawnType(), and SP_NPC_Droid_Mark2().

00028 {
00029         G_SoundIndex( "sound/chars/mark2/misc/mark2_explo" );// blows up on death
00030         G_SoundIndex( "sound/chars/mark2/misc/mark2_pain" );
00031         G_SoundIndex( "sound/chars/mark2/misc/mark2_fire" );
00032         G_SoundIndex( "sound/chars/mark2/misc/mark2_move_lp" );
00033 
00034         G_EffectIndex( "explosions/droidexplosion1" );
00035         G_EffectIndex( "env/med_explode2" );
00036         G_EffectIndex( "blaster/smoke_bolton" );
00037         G_EffectIndex( "bryar/muzzle_flash" );
00038 
00039         RegisterItem( BG_FindItemForWeapon( WP_BRYAR_PISTOL ));
00040         RegisterItem( BG_FindItemForAmmo(       AMMO_METAL_BOLTS));
00041         RegisterItem( BG_FindItemForAmmo( AMMO_POWERCELL ));
00042         RegisterItem( BG_FindItemForAmmo( AMMO_BLASTER ));
00043 }