codemp/game/ai.h File Reference

Go to the source code of this file.

Data Structures

struct  AIGroupInfo_s
struct  AIGroupMember_s

Defines

#define MAX_FRAME_GROUPS   32
#define MAX_GROUP_MEMBERS   32

Typedefs

typedef AIGroupMember_s AIGroupMember_t
typedef AIGroupInfo_s AIGroupInfo_t

Enumerations

enum  distance_e { DIST_MELEE, DIST_LONG }
enum  attack_e { ATTACK_MELEE, ATTACK_RANGE }
enum  {
  SQUAD_IDLE, SQUAD_STAND_AND_SHOOT, SQUAD_RETREAT, SQUAD_COVER,
  SQUAD_TRANSITION, SQUAD_POINT, SQUAD_SCOUT, NUM_SQUAD_STATES
}
enum  rank_t {
  RANK_CIVILIAN, RANK_CREWMAN, RANK_ENSIGN, RANK_LT_JG,
  RANK_LT, RANK_LT_COMM, RANK_COMMANDER, RANK_CAPTAIN
}

Functions

qboolean NPC_CheckPlayerTeamStealth (void)
void NPC_BSGrenadier_Default (void)
void NPC_BSSniper_Default (void)
void NPC_BSST_Investigate (void)
void NPC_BSST_Default (void)
void NPC_BSST_Sleep (void)
void NPC_BSJedi_Investigate (void)
void NPC_BSJedi_Default (void)
void NPC_BSJedi_FollowLeader (void)
void NPC_BSDroid_Default (void)
void NPC_BSImperialProbe_Default (void)
void NPC_BSATST_Default (void)
void NPC_BSInterrogator_Default (void)
void NPC_BSMark1_Default (void)
void NPC_BSMark2_Default (void)
void NPC_BSMineMonster_Default (void)
void NPC_BSHowler_Default (void)
void NPC_BSRancor_Default (void)
int AI_GetGroupSize (vec3_t origin, int radius, team_t playerTeam, gentity_t *avoid)
int AI_GetGroupSize2 (gentity_t *ent, int radius)
void AI_GetGroup (gentity_t *self)
qboolean AI_CheckEnemyCollision (gentity_t *ent, qboolean takeEnemy)
gentity_tAI_DistributeAttack (gentity_t *attacker, gentity_t *enemy, team_t team, int threshold)


Define Documentation

#define MAX_FRAME_GROUPS   32
 

Definition at line 85 of file ai.h.

Referenced by AI_FindSelfInPreviousGroup(), AI_GetNextEmptyGroup(), AI_RefreshGroup(), AI_TryJoinPreviousGroup(), and AI_UpdateGroups().

#define MAX_GROUP_MEMBERS   32
 

Definition at line 95 of file ai.h.

Referenced by AI_GetGroup(), AI_RefreshGroup(), AI_SortGroupByPathCostToEnemy(), and AI_TryJoinPreviousGroup().


Typedef Documentation

typedef struct AIGroupInfo_s AIGroupInfo_t
 

Referenced by AI_ClosestGroupEntityNumToPoint(), AI_DeleteGroupMember(), AI_GetGroup(), AI_GroupContainsEntNum(), AI_GroupMemberKilled(), AI_GroupUpdateClearShotTime(), AI_GroupUpdateEnemyLastSeen(), AI_GroupUpdateSquadstates(), AI_InsertGroupMember(), AI_RefreshGroup(), AI_SetClosestBuddy(), AI_SetNewGroupCommander(), AI_SortGroupByPathCostToEnemy(), AI_ValidateGroupMember(), AI_ValidateNoEnemyGroupMember(), and ST_Commander().

typedef struct AIGroupMember_s AIGroupMember_t
 

Referenced by AI_SortGroupByPathCostToEnemy().


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
SQUAD_IDLE 
SQUAD_STAND_AND_SHOOT 
SQUAD_RETREAT 
SQUAD_COVER 
SQUAD_TRANSITION 
SQUAD_POINT 
SQUAD_SCOUT 
NUM_SQUAD_STATES 

Definition at line 18 of file ai.h.

00019 {
00020         SQUAD_IDLE,                                     //No target found, waiting
00021         SQUAD_STAND_AND_SHOOT,          //Standing in position and shoot (no cover)
00022         SQUAD_RETREAT,                          //Running away from combat
00023         SQUAD_COVER,                            //Under protective cover
00024         SQUAD_TRANSITION,                       //Moving between points, not firing
00025         SQUAD_POINT,                            //On point, laying down suppressive fire
00026         SQUAD_SCOUT,                            //Poking out to draw enemy
00027         NUM_SQUAD_STATES,
00028 };

enum attack_e
 

Enumeration values:
ATTACK_MELEE 
ATTACK_RANGE 

Definition at line 12 of file ai.h.

00013 {
00014         ATTACK_MELEE,
00015         ATTACK_RANGE,
00016 } attack_e;

enum distance_e
 

Enumeration values:
DIST_MELEE 
DIST_LONG 

Definition at line 5 of file ai.h.

Referenced by ATST_Attack(), and Mark1_AttackDecision().

00006 {
00007         DIST_MELEE,
00008         DIST_LONG,
00009 } distance_e;

enum rank_t
 

Enumeration values:
RANK_CIVILIAN 
RANK_CREWMAN 
RANK_ENSIGN 
RANK_LT_JG 
RANK_LT 
RANK_LT_COMM 
RANK_COMMANDER 
RANK_CAPTAIN 

Definition at line 31 of file ai.h.

00032 {
00033         RANK_CIVILIAN,
00034         RANK_CREWMAN,
00035         RANK_ENSIGN,
00036         RANK_LT_JG,
00037         RANK_LT,
00038         RANK_LT_COMM,
00039         RANK_COMMANDER,
00040         RANK_CAPTAIN
00041 } rank_t;


Function Documentation

qboolean AI_CheckEnemyCollision gentity_t ent,
qboolean  takeEnemy
 

Definition at line 1030 of file NPC_AI_Utils.c.

References navInfo_s::blocker, gentity_s::client, gentity_s::enemy, gclient_s::enemyTeam, G_SetEnemy(), gentity_t, NAV_GetLastMove(), navInfo_t, NULL, gclient_s::playerTeam, qboolean, qfalse, and qtrue.

01031 {
01032         navInfo_t       info;
01033 
01034         if ( ent == NULL )
01035                 return qfalse;
01036 
01037 //      if ( ent->svFlags & SVF_LOCKEDENEMY )
01038 //              return qfalse;
01039 
01040         NAV_GetLastMove( &info );
01041 
01042         //See if we've hit something
01043         if ( ( info.blocker ) && ( info.blocker != ent->enemy ) )
01044         {
01045                 if ( ( info.blocker->client ) && ( info.blocker->client->playerTeam == ent->client->enemyTeam ) )
01046                 {
01047                         if ( takeEnemy )
01048                                 G_SetEnemy( ent, info.blocker );
01049 
01050                         return qtrue;
01051                 }
01052         }
01053 
01054         return qfalse;
01055 }

gentity_t* AI_DistributeAttack gentity_t attacker,
gentity_t enemy,
team_t  team,
int  threshold
 

Definition at line 1065 of file NPC_AI_Utils.c.

References AI_GetGroupSize(), gentity_s::client, entityShared_t::currentOrigin, g_entities, gentity_t, gentity_s::health, MAX_RADIUS_ENTS, NULL, gclient_s::playerTeam, gentity_s::r, team_t, trap_EntitiesInBox(), and vec3_t.

01066 {
01067         int                     radiusEnts[ MAX_RADIUS_ENTS ];
01068         gentity_t       *check;
01069         int                     numEnts;
01070         int                     numSurrounding;
01071         int                     i;
01072         int                     j;
01073         vec3_t          mins, maxs;
01074 
01075         //Don't take new targets
01076 //      if ( NPC->svFlags & SVF_LOCKEDENEMY )
01077 //              return enemy;
01078 
01079         numSurrounding = AI_GetGroupSize( enemy->r.currentOrigin, 48, team, attacker );
01080 
01081         //First, see if we should look for the player
01082         if ( enemy != &g_entities[0] )
01083         {
01084                 //rwwFIXMEFIXME: care about all clients not just 0
01085                 int     aroundPlayer = AI_GetGroupSize( g_entities[0].r.currentOrigin, 48, team, attacker );
01086 
01087                 //See if we're above our threshold
01088                 if ( aroundPlayer < threshold )
01089                 {
01090                         return &g_entities[0];
01091                 }
01092         }
01093 
01094         //See if our current enemy is still ok
01095         if ( numSurrounding < threshold )
01096                 return enemy;
01097 
01098         //Otherwise we need to take a new enemy if possible
01099 
01100         //Setup the bbox to search in
01101         for ( i = 0; i < 3; i++ )
01102         {
01103                 mins[i] = enemy->r.currentOrigin[i] - 512;
01104                 maxs[i] = enemy->r.currentOrigin[i] + 512;
01105         }
01106 
01107         //Get the number of entities in a given space
01108         numEnts = trap_EntitiesInBox( mins, maxs, radiusEnts, MAX_RADIUS_ENTS );
01109 
01110         //Cull this list
01111         for ( j = 0; j < numEnts; j++ )
01112         {
01113                 check = &g_entities[radiusEnts[j]];
01114 
01115                 //Validate clients
01116                 if ( check->client == NULL )
01117                         continue;
01118 
01119                 //Skip the requested avoid ent if present
01120                 if ( ( check == enemy ) )
01121                         continue;
01122 
01123                 //Must be on the same team
01124                 if ( check->client->playerTeam != enemy->client->playerTeam )
01125                         continue;
01126 
01127                 //Must be alive
01128                 if ( check->health <= 0 )
01129                         continue;
01130 
01131                 //Must not be overwhelmed
01132                 if ( AI_GetGroupSize( check->r.currentOrigin, 48, team, attacker ) > threshold )
01133                         continue;
01134 
01135                 return check;
01136         }
01137 
01138         return NULL;
01139 }

void AI_GetGroup gentity_t self  ) 
 

Definition at line 443 of file NPC_AI_Utils.c.

References AIGroupInfo_s::activeMemberNum, AI_GetNextEmptyGroup(), AI_InsertGroupMember(), AI_SetClosestBuddy(), AI_SortGroupByPathCostToEnemy(), AI_ValidateGroupMember(), AIGroupInfo_t, gentity_s::client, AIGroupInfo_s::commander, entityShared_t::currentOrigin, d_noGroupAI, gentity_s::enemy, AIGroupInfo_s::enemy, AIGroupInfo_s::enemyLastSeenPos, gNPC_t::enemyLastSeenTime, g_entities, gentity_t, gNPC_t::group, vmCvar_t::integer, gentity_s::inuse, AIGroupInfo_s::lastClearShotTime, AIGroupInfo_s::lastSeenEnemyTime, level, MAX_GROUP_MEMBERS, AIGroupInfo_s::memberValidateTime, memset(), gentity_s::NPC, NULL, level_locals_t::num_entities, AIGroupInfo_s::numGroup, gclient_s::playerTeam, AIGroupInfo_s::processed, qfalse, gentity_s::r, SCF_NO_GROUPS, gNPC_t::scriptFlags, AIGroupInfo_s::team, level_locals_t::time, and VectorCopy.

Referenced by NPC_BSST_Attack(), NPC_BSST_Investigate(), and NPC_BSST_Patrol().

00444 {
00445         int     i;
00446         gentity_t       *member;//, *waiter;
00447         //int   waiters[MAX_WAITERS];
00448 
00449         if ( !self || !self->NPC )
00450         {
00451                 return;
00452         }
00453 
00454         if ( d_noGroupAI.integer )
00455         {
00456                 self->NPC->group = NULL;
00457                 return;
00458         }
00459 
00460         if ( !self->client )
00461         {
00462                 self->NPC->group = NULL;
00463                 return;
00464         }
00465 
00466         if ( self->NPC->scriptFlags&SCF_NO_GROUPS )
00467         {
00468                 self->NPC->group = NULL;
00469                 return;
00470         }
00471 
00472         if ( self->enemy && (!self->enemy->client || (level.time - self->NPC->enemyLastSeenTime > 7000 )))
00473         {
00474                 self->NPC->group = NULL;
00475                 return;
00476         }
00477 
00478         if ( !AI_GetNextEmptyGroup( self ) )
00479         {//either no more groups left or we're already in a group built earlier
00480                 return;
00481         }
00482 
00483         //create a new one
00484         memset( self->NPC->group, 0, sizeof( AIGroupInfo_t ) );
00485 
00486         self->NPC->group->enemy = self->enemy;
00487         self->NPC->group->team = self->client->playerTeam;
00488         self->NPC->group->processed = qfalse;
00489         self->NPC->group->commander = self;
00490         self->NPC->group->memberValidateTime = level.time + 2000;
00491         self->NPC->group->activeMemberNum = 0;
00492 
00493         if ( self->NPC->group->enemy )
00494         {
00495                 self->NPC->group->lastSeenEnemyTime = level.time;
00496                 self->NPC->group->lastClearShotTime = level.time;
00497                 VectorCopy( self->NPC->group->enemy->r.currentOrigin, self->NPC->group->enemyLastSeenPos );
00498         }
00499 
00500 //      for ( i = 0, member = &g_entities[0]; i < globals.num_entities ; i++, member++)
00501         for ( i = 0; i < level.num_entities ; i++)
00502         {
00503                 member = &g_entities[i];
00504 
00505                 if (!member->inuse)
00506                 {
00507                         continue;
00508                 }
00509 
00510                 if ( !AI_ValidateGroupMember( self->NPC->group, member ) )
00511                 {//FIXME: keep track of those who aren't angry yet and see if we should wake them after we assemble the core group
00512                         continue;
00513                 }
00514                 
00515                 //store it
00516                 AI_InsertGroupMember( self->NPC->group, member );
00517 
00518                 if ( self->NPC->group->numGroup >= (MAX_GROUP_MEMBERS - 1) )
00519                 {//full
00520                         break;
00521                 }
00522         }
00523 
00524         /*
00525         //now go through waiters and see if any should join the group
00526         //NOTE:  Some should hang back and probably not attack, so we can ambush
00527         //NOTE: only do this if calling for reinforcements?
00528         for ( i = 0; i < numWaiters; i++ )
00529         {
00530                 waiter = &g_entities[waiters[i]];
00531         
00532                 for ( j = 0; j < self->NPC->group->numGroup; j++ )
00533                 {
00534                         member = &g_entities[self->NPC->group->member[j];
00535 
00536                         if ( trap_InPVS( waiter->r.currentOrigin, member->r.currentOrigin ) )
00537                         {//this waiter is within PVS of a current member
00538                         }
00539                 }
00540         }
00541         */
00542 
00543         if ( self->NPC->group->numGroup <= 0 )
00544         {//none in group
00545                 self->NPC->group = NULL;
00546                 return;
00547         }
00548 
00549         AI_SortGroupByPathCostToEnemy( self->NPC->group );
00550         AI_SetClosestBuddy( self->NPC->group );
00551 }

int AI_GetGroupSize vec3_t  origin,
int  radius,
team_t  playerTeam,
gentity_t avoid
 

Definition at line 23 of file NPC_AI_Utils.c.

References gentity_s::client, g_entities, gentity_t, gentity_s::health, MAX_RADIUS_ENTS, NULL, gclient_s::playerTeam, team_t, trap_EntitiesInBox(), and vec3_t.

Referenced by AI_DistributeAttack(), and AI_GetGroupSize2().

00024 {
00025         int                     radiusEnts[ MAX_RADIUS_ENTS ];
00026         gentity_t       *check;
00027         vec3_t          mins, maxs;
00028         int                     numEnts, realCount = 0;
00029         int                     i;
00030         int                     j;
00031 
00032         //Setup the bbox to search in
00033         for ( i = 0; i < 3; i++ )
00034         {
00035                 mins[i] = origin[i] - radius;
00036                 maxs[i] = origin[i] + radius;
00037         }
00038 
00039         //Get the number of entities in a given space
00040         numEnts = trap_EntitiesInBox( mins, maxs, radiusEnts, MAX_RADIUS_ENTS );
00041 
00042         //Cull this list
00043         for ( j = 0; j < numEnts; j++ )
00044         {
00045                 check = &g_entities[radiusEnts[j]];
00046 
00047                 //Validate clients
00048                 if ( check->client == NULL )
00049                         continue;
00050 
00051                 //Skip the requested avoid ent if present
00052                 if ( ( avoid != NULL ) && ( check == avoid ) )
00053                         continue;
00054 
00055                 //Must be on the same team
00056                 if ( check->client->playerTeam != playerTeam )
00057                         continue;
00058 
00059                 //Must be alive
00060                 if ( check->health <= 0 )
00061                         continue;
00062 
00063                 realCount++;
00064         }
00065 
00066         return realCount;
00067 }

int AI_GetGroupSize2 gentity_t ent,
int  radius
 

Definition at line 71 of file NPC_AI_Utils.c.

References AI_GetGroupSize(), gentity_s::client, entityShared_t::currentOrigin, gentity_t, NULL, gclient_s::playerTeam, and gentity_s::r.

00072 {
00073         if ( ( ent == NULL ) || ( ent->client == NULL ) )
00074                 return -1;
00075 
00076         return AI_GetGroupSize( ent->r.currentOrigin, radius, ent->client->playerTeam, ent );
00077 }

void NPC_BSATST_Default void   ) 
 

Definition at line 310 of file NPC_AI_Atst.c.

References ATST_Attack(), ATST_Idle(), ATST_Patrol(), gentity_s::enemy, gNPC_t::goalEntity, NPC, NPCInfo, SCF_CHASE_ENEMIES, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_ATST().

00311 {
00312         if ( NPC->enemy )
00313         {
00314                 if( (NPCInfo->scriptFlags & SCF_CHASE_ENEMIES) )
00315                 {
00316                         NPCInfo->goalEntity = NPC->enemy;
00317                 }
00318                 ATST_Attack();
00319         }
00320         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00321         {
00322                 ATST_Patrol();
00323         } 
00324         else
00325         {
00326                 ATST_Idle();
00327         }
00328 }

void NPC_BSDroid_Default void   ) 
 

Definition at line 597 of file NPC_AI_Droid.c.

References crandom, Droid_Pain(), Droid_Patrol(), Droid_Run(), Droid_Spin(), gNPC_t::localState, LSTATE_DROP, LSTATE_PAIN, LSTATE_SPINNING, NPC_UpdateAngles(), NPCInfo, qtrue, SCF_LOOK_FOR_ENEMIES, gNPC_t::scriptFlags, ucmd, and usercmd_s::upmove.

Referenced by NPC_BehaviorSet_Droid().

00598 {
00599 
00600         if ( NPCInfo->localState == LSTATE_SPINNING )
00601         {
00602                 Droid_Spin();
00603         }
00604         else if ( NPCInfo->localState == LSTATE_PAIN )
00605         {
00606                 Droid_Pain();
00607         }
00608         else if ( NPCInfo->localState == LSTATE_DROP )
00609         {
00610                 NPC_UpdateAngles( qtrue, qtrue );
00611                 ucmd.upmove = crandom() * 64;
00612         }
00613         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00614         {
00615                 Droid_Patrol();
00616         }
00617         else
00618         {
00619                 Droid_Run();
00620         }
00621 }

void NPC_BSGrenadier_Default void   ) 
 

Definition at line 664 of file NPC_AI_Grenadier.c.

References gentity_s::enemy, NPC, NPC_BSGrenadier_Attack(), NPC_BSGrenadier_Patrol(), NPCInfo, qtrue, SCF_FIRE_WEAPON, gNPC_t::scriptFlags, and WeaponThink().

Referenced by NPC_BehaviorSet_Grenadier().

00665 {
00666         if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON )
00667         {
00668                 WeaponThink( qtrue );
00669         }
00670 
00671         if( !NPC->enemy )
00672         {//don't have an enemy, look for one
00673                 NPC_BSGrenadier_Patrol();
00674         }
00675         else//if ( NPC->enemy )
00676         {//have an enemy
00677                 NPC_BSGrenadier_Attack();
00678         }
00679 }

void NPC_BSHowler_Default void   ) 
 

Definition at line 202 of file NPC_AI_Howler.c.

References gentity_s::enemy, Howler_Combat(), Howler_Idle(), Howler_Patrol(), NPC, NPC_UpdateAngles(), NPCInfo, qtrue, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_Howler().

00203 {
00204         if ( NPC->enemy )
00205         {
00206                 Howler_Combat();
00207         }
00208         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00209         {
00210                 Howler_Patrol();
00211         }
00212         else
00213         {
00214                 Howler_Idle();
00215         }
00216 
00217         NPC_UpdateAngles( qtrue, qtrue );
00218 }

void NPC_BSImperialProbe_Default void   ) 
 

Definition at line 589 of file NPC_AI_ImperialProbe.c.

References gentity_s::enemy, gNPC_t::goalEntity, ImperialProbe_AttackDecision(), ImperialProbe_Idle(), ImperialProbe_Patrol(), ImperialProbe_Wait(), gNPC_t::localState, LSTATE_DROP, NPC, NPCInfo, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_ImperialProbe().

00590 {
00591 
00592         if ( NPC->enemy )
00593         {
00594                 NPCInfo->goalEntity = NPC->enemy;
00595                 ImperialProbe_AttackDecision();
00596         }
00597         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00598         {
00599                 ImperialProbe_Patrol();
00600         }
00601         else if ( NPCInfo->localState == LSTATE_DROP )
00602         {
00603                 ImperialProbe_Wait();
00604         }
00605         else
00606         {
00607                 ImperialProbe_Idle();
00608         }
00609 }

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_BSJedi_Default void   ) 
 

Definition at line 6170 of file NPC_AI_Jedi.c.

References Boba_ChangeWeapon(), usercmd_s::buttons, CLASS_BOBAFETT, gentity_s::client, gNPC_t::confusionTime, entityShared_t::currentOrigin, gentity_s::enemy, gNPC_t::enemyCheckDebounceTime, playerState_s::fd, forcedata_s::forcePowersActive, G_SetEnemy(), gentity_t, gentity_s::health, Jedi_Ambush(), Jedi_CheckCloak(), Jedi_WaitingAmbush(), gentity_s::lastEnemy, level, clientPersistant_t::maxHealth, NPC, NPC_BSSniper_Default(), NPC_BSST_Patrol(), NPC_CheckEnemy(), gclient_s::NPC_class, NPCInfo, NULL, gclient_s::pers, gclient_s::ps, Q_irand(), qfalse, gentity_s::r, SCF_ALT_FIRE, gNPC_t::scriptFlags, level_locals_t::time, ucmd, and WP_DISRUPTOR.

Referenced by NPC_BehaviorSet_Jedi().

06171 {
06172 
06173         Jedi_CheckCloak();
06174         if( !NPC->enemy )
06175         {//don't have an enemy, look for one
06176                 if ( NPC->client->NPC_class == CLASS_BOBAFETT )
06177                 {
06178                         NPC_BSST_Patrol();
06179                 }
06180                 else
06181                 {
06182                         Jedi_Patrol();
06183                 }
06184         }
06185         else//if ( NPC->enemy )
06186         {//have an enemy
06187                 if ( Jedi_WaitingAmbush( NPC ) )
06188                 {//we were still waiting to drop down - must have had enemy set on me outside my AI
06189                         Jedi_Ambush( NPC );
06190                 }
06191                 if ( NPC->client->NPC_class == CLASS_BOBAFETT )
06192                 {
06193                         if ( NPC->enemy->enemy != NPC && NPC->health == NPC->client->pers.maxHealth && DistanceSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin )>(800*800) )
06194                         {
06195                                 NPCInfo->scriptFlags |= SCF_ALT_FIRE;
06196                                 Boba_ChangeWeapon( WP_DISRUPTOR );
06197                                 NPC_BSSniper_Default();
06198                                 return;
06199                         }
06200                 }
06201                 Jedi_Attack();
06202                 //if we have multiple-jedi combat, probably need to keep checking (at certain debounce intervals) for a better (closer, more active) enemy and switch if needbe...
06203                 if ( ((!ucmd.buttons&&!NPC->client->ps.fd.forcePowersActive)||(NPC->enemy&&NPC->enemy->health<=0)) && NPCInfo->enemyCheckDebounceTime < level.time )
06204                 {//not doing anything (or walking toward a vanquished enemy - fixme: always taunt the player?), not using force powers and it's time to look again
06205                         //FIXME: build a list of all local enemies (since we have to find best anyway) for other AI factors- like when to use group attacks, determine when to change tactics, when surrounded, when blocked by another in the enemy group, etc.  Should we build this group list or let the enemies maintain their own list and we just access it?
06206                         gentity_t *sav_enemy = NPC->enemy;//FIXME: what about NPC->lastEnemy?
06207                         gentity_t *newEnemy;
06208 
06209                         NPC->enemy = NULL;
06210                         newEnemy = NPC_CheckEnemy( NPCInfo->confusionTime < level.time, qfalse, qfalse );
06211                         NPC->enemy = sav_enemy;
06212                         if ( newEnemy && newEnemy != sav_enemy )
06213                         {//picked up a new enemy!
06214                                 NPC->lastEnemy = NPC->enemy;
06215                                 G_SetEnemy( NPC, newEnemy );
06216                         }
06217                         NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 1000, 3000 );
06218                 }
06219         }
06220 }

void NPC_BSJedi_FollowLeader void   ) 
 

Definition at line 5758 of file NPC_AI_Jedi.c.

References gNPC_t::aiFlags, BLOCKED_NONE, gNPC_t::blockedDest, BUTTON_ATTACK, usercmd_s::buttons, gentity_s::client, gentity_s::clipmask, CONTENTS_BODY, CONTENTS_BOTCLIP, entityShared_t::currentOrigin, gentity_s::enemy, ENTITYNUM_NONE, fabs(), g_entities, G_FreeEntity(), G_SetOrigin(), G_Spawn(), gentity_t, gNPC_t::goalEntity, gentity_s::health, Jedi_CanPullBackSaber(), NAV_CheckAhead(), NPC, NPC_BSFollowLeader(), NPC_ClearLOS4(), NPC_FaceEntity(), NPC_MoveToGoal(), NPC_UpdateAngles(), NPCAI_BLOCKED, NPCInfo, gclient_s::ps, qtrue, gentity_s::r, playerState_s::saberBlocked, playerState_s::saberEntityNum, playerState_s::saberInFlight, TIMER_Set(), TR_STATIONARY, trap_LinkEntity(), and ucmd.

Referenced by NPC_BehaviorSet_Jedi().

05759 {
05760         NPC->client->ps.saberBlocked = BLOCKED_NONE;
05761         if ( !NPC->enemy )
05762         {
05763                 //Com_Printf( "(%d) drop agg - no enemy (follow)\n", level.time );
05764                 Jedi_AggressionErosion(-1);
05765         }
05766         
05767         //did we drop our saber?  If so, go after it!
05768         if ( NPC->client->ps.saberInFlight )
05769         {//saber is not in hand
05770                 if ( NPC->client->ps.saberEntityNum < ENTITYNUM_NONE && NPC->client->ps.saberEntityNum > 0 )//player is 0
05771                 {//
05772                         if ( g_entities[NPC->client->ps.saberEntityNum].s.pos.trType == TR_STATIONARY )
05773                         {//fell to the ground, try to pick it up... 
05774                                 if ( Jedi_CanPullBackSaber( NPC ) )
05775                                 {
05776                                         //FIXME: if it's on the ground and we just pulled it back to us, should we
05777                                         //              stand still for a bit to make sure it gets to us...?
05778                                         //              otherwise we could end up running away from it while it's on its
05779                                         //              way back to us and we could lose it again.
05780                                         NPC->client->ps.saberBlocked = BLOCKED_NONE;
05781                                         NPCInfo->goalEntity = &g_entities[NPC->client->ps.saberEntityNum];
05782                                         ucmd.buttons |= BUTTON_ATTACK;
05783                                         if ( NPC->enemy && NPC->enemy->health > 0 )
05784                                         {//get our saber back NOW!
05785                                                 if ( !NPC_MoveToGoal( qtrue ) )//Jedi_Move( NPCInfo->goalEntity, qfalse );
05786                                                 {//can't nav to it, try jumping to it
05787                                                         NPC_FaceEntity( NPCInfo->goalEntity, qtrue );
05788                                                         Jedi_TryJump( NPCInfo->goalEntity );
05789                                                 }
05790                                                 NPC_UpdateAngles( qtrue, qtrue );
05791                                                 return;
05792                                         }
05793                                 }
05794                         }
05795                 }
05796         }
05797 
05798         if ( NPCInfo->goalEntity )
05799         {
05800                 trace_t trace;
05801 
05802                 if ( Jedi_Jumping( NPCInfo->goalEntity ) )
05803                 {//in mid-jump
05804                         return;
05805                 }
05806 
05807                 if ( !NAV_CheckAhead( NPC, NPCInfo->goalEntity->r.currentOrigin, &trace, ( NPC->clipmask & ~CONTENTS_BODY )|CONTENTS_BOTCLIP ) )
05808                 {//can't get straight to him
05809                         if ( NPC_ClearLOS4( NPCInfo->goalEntity ) && NPC_FaceEntity( NPCInfo->goalEntity, qtrue ) )
05810                         {//no line of sight
05811                                 if ( Jedi_TryJump( NPCInfo->goalEntity ) )
05812                                 {//started a jump
05813                                         return;
05814                                 }
05815                         }
05816                 }
05817                 if ( NPCInfo->aiFlags & NPCAI_BLOCKED )
05818                 {//try to jump to the blockedDest
05819                         if ( fabs(NPCInfo->blockedDest[2]-NPC->r.currentOrigin[2]) > 64 )
05820                         {
05821                                 gentity_t *tempGoal = G_Spawn();//ugh, this is NOT good...?
05822                                 G_SetOrigin( tempGoal, NPCInfo->blockedDest );
05823                                 trap_LinkEntity( tempGoal );
05824                                 TIMER_Set( NPC, "jumpChaseDebounce", -1 );
05825                                 if ( Jedi_TryJump( tempGoal ) )
05826                                 {//going to jump to the dest
05827                                         G_FreeEntity( tempGoal );
05828                                         return;
05829                                 }
05830                                 G_FreeEntity( tempGoal );
05831                         }
05832                 }
05833         }
05834         //try normal movement
05835         NPC_BSFollowLeader();
05836 }

void NPC_BSJedi_Investigate void   ) 
 

void NPC_BSMark1_Default void   ) 
 

Definition at line 747 of file NPC_AI_Mark1.c.

References gentity_s::enemy, gNPC_t::goalEntity, Mark1_AttackDecision(), Mark1_Idle(), Mark1_Patrol(), NPC, NPCInfo, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_Mark1().

00748 {
00749         //NPC->e_DieFunc = dieF_Mark1_die;
00750 
00751         if ( NPC->enemy )
00752         {
00753                 NPCInfo->goalEntity = NPC->enemy;
00754                 Mark1_AttackDecision();
00755         }
00756         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00757         {
00758                 Mark1_Patrol();
00759         }
00760         else
00761         {
00762                 Mark1_Idle();
00763         }
00764 }

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_BSMineMonster_Default void   ) 
 

Definition at line 262 of file NPC_AI_MineMonster.c.

References gentity_s::enemy, MineMonster_Combat(), MineMonster_Idle(), MineMonster_Patrol(), NPC, NPC_UpdateAngles(), NPCInfo, qtrue, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_MineMonster().

00263 {
00264         if ( NPC->enemy )
00265         {
00266                 MineMonster_Combat();
00267         }
00268         else if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00269         {
00270                 MineMonster_Patrol();
00271         }
00272         else
00273         {
00274                 MineMonster_Idle();
00275         }
00276 
00277         NPC_UpdateAngles( qtrue, qtrue );
00278 }

void NPC_BSRancor_Default void   ) 
 

Definition at line 828 of file NPC_AI_Rancor.c.

References gentity_s::activator, AddSightEvent(), AddSoundEvent(), AEL_DANGER, AEL_DANGER_GREAT, BOTH_ATTACK3, BOTH_PAIN2, CHAN_AUTO, CLASS_RANCOR, gentity_s::client, gNPC_t::confusionTime, gentity_s::count, entityShared_t::currentOrigin, EF2_GENERIC_NPC_FLAG, EF2_USE_ALT_ANIM, playerState_s::eFlags2, gentity_s::enemy, G_SetEnemy(), G_Sound(), G_SoundIndex(), gentity_t, gentity_s::inuse, gentity_s::lastEnemy, playerState_s::legsAnim, level, NPC, NPC_CheckEnemy(), NPC_CheckEnemyExt(), gclient_s::NPC_class, NPC_FaceEnemy(), NPC_UpdateAngles(), NPCInfo, NULL, gclient_s::ps, Q_irand(), qfalse, qtrue, gentity_s::r, Rancor_CheckDropVictim(), Rancor_Combat(), Rancor_Crush(), Rancor_DropVictim(), Rancor_Idle(), Rancor_Patrol(), gentity_s::s, SCF_LOOK_FOR_ENEMIES, gNPC_t::scriptFlags, level_locals_t::time, entityState_s::time, TIMER_Done(), TIMER_Done2(), TIMER_Remove(), TIMER_Set(), va(), and ValidEnemy().

Referenced by NPC_BehaviorSet_Rancor().

00829 {
00830         AddSightEvent( NPC, NPC->r.currentOrigin, 1024, AEL_DANGER_GREAT, 50 );
00831 
00832         Rancor_Crush();
00833 
00834         NPC->client->ps.eFlags2 &= ~(EF2_USE_ALT_ANIM|EF2_GENERIC_NPC_FLAG);
00835         if ( NPC->count )
00836         {//holding someone
00837                 NPC->client->ps.eFlags2 |= EF2_USE_ALT_ANIM;
00838                 if ( NPC->count == 2 )
00839                 {//in my mouth
00840                         NPC->client->ps.eFlags2 |= EF2_GENERIC_NPC_FLAG;
00841                 }
00842         }
00843         else
00844         {
00845                 NPC->client->ps.eFlags2 &= ~(EF2_USE_ALT_ANIM|EF2_GENERIC_NPC_FLAG);
00846         }
00847 
00848         if ( TIMER_Done2( NPC, "clearGrabbed", qtrue ) )
00849         {
00850                 Rancor_DropVictim( NPC );
00851         }
00852         else if ( NPC->client->ps.legsAnim == BOTH_PAIN2 
00853                 && NPC->count == 1 
00854                 && NPC->activator )
00855         {
00856                 if ( !Q_irand( 0, 3 ) )
00857                 {
00858                         Rancor_CheckDropVictim();
00859                 }
00860         }
00861         if ( !TIMER_Done( NPC, "rageTime" ) )
00862         {//do nothing but roar first time we see an enemy
00863                 AddSoundEvent( NPC, NPC->r.currentOrigin, 1024, AEL_DANGER_GREAT, qfalse );//, qfalse );
00864                 NPC_FaceEnemy( qtrue );
00865                 return;
00866         }
00867         if ( NPC->enemy )
00868         {
00869                 /*
00870                 if ( NPC->enemy->client //enemy is a client
00871                         && (NPC->enemy->client->NPC_class == CLASS_UGNAUGHT || NPC->enemy->client->NPC_class == CLASS_JAWA )//enemy is a lowly jawa or ugnaught
00872                         && NPC->enemy->enemy != NPC//enemy's enemy is not me
00873                         && (!NPC->enemy->enemy || !NPC->enemy->enemy->client || NPC->enemy->enemy->client->NPC_class!=CLASS_RANCOR) )//enemy's enemy is not a client or is not a rancor (which is as scary as me anyway)
00874                 {//they should be scared of ME and no-one else
00875                         G_SetEnemy( NPC->enemy, NPC );
00876                 }
00877                 */
00878                 if ( TIMER_Done(NPC,"angrynoise") )
00879                 {
00880                         G_Sound( NPC, CHAN_AUTO, G_SoundIndex( va("sound/chars/rancor/misc/anger%d.wav", Q_irand(1, 3))) );
00881 
00882                         TIMER_Set( NPC, "angrynoise", Q_irand( 5000, 10000 ) );
00883                 }
00884                 else
00885                 {
00886                         AddSoundEvent( NPC, NPC->r.currentOrigin, 512, AEL_DANGER_GREAT, qfalse );//, qfalse );
00887                 }
00888                 if ( NPC->count == 2 && NPC->client->ps.legsAnim == BOTH_ATTACK3 )
00889                 {//we're still chewing our enemy up
00890                         NPC_UpdateAngles( qtrue, qtrue );
00891                         return;
00892                 }
00893                 //else, if he's in our hand, we eat, else if he's on the ground, we keep attacking his dead body for a while
00894                 if( NPC->enemy->client && NPC->enemy->client->NPC_class == CLASS_RANCOR )
00895                 {//got mad at another Rancor, look for a valid enemy
00896                         if ( TIMER_Done( NPC, "rancorInfight" ) )
00897                         {
00898                                 NPC_CheckEnemyExt( qtrue );
00899                         }
00900                 }
00901                 else if ( !NPC->count )
00902                 {
00903                         if ( ValidEnemy( NPC->enemy ) == qfalse )
00904                         {
00905                                 TIMER_Remove( NPC, "lookForNewEnemy" );//make them look again right now
00906                                 if ( !NPC->enemy->inuse || level.time - NPC->enemy->s.time > Q_irand( 10000, 15000 ) )
00907                                 {//it's been a while since the enemy died, or enemy is completely gone, get bored with him
00908                                         NPC->enemy = NULL;
00909                                         Rancor_Patrol();
00910                                         NPC_UpdateAngles( qtrue, qtrue );
00911                                         return;
00912                                 }
00913                         }
00914                         if ( TIMER_Done( NPC, "lookForNewEnemy" ) )
00915                         {
00916                                 gentity_t *newEnemy, *sav_enemy = NPC->enemy;//FIXME: what about NPC->lastEnemy?
00917                                 NPC->enemy = NULL;
00918                                 newEnemy = NPC_CheckEnemy( NPCInfo->confusionTime < level.time, qfalse, qfalse );
00919                                 NPC->enemy = sav_enemy;
00920                                 if ( newEnemy && newEnemy != sav_enemy )
00921                                 {//picked up a new enemy!
00922                                         NPC->lastEnemy = NPC->enemy;
00923                                         G_SetEnemy( NPC, newEnemy );
00924                                         //hold this one for at least 5-15 seconds
00925                                         TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
00926                                 }
00927                                 else
00928                                 {//look again in 2-5 secs
00929                                         TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 2000, 5000 ) );
00930                                 }
00931                         }
00932                 }
00933                 Rancor_Combat();
00934         }
00935         else 
00936         {
00937                 if ( TIMER_Done(NPC,"idlenoise") )
00938                 {
00939                         G_Sound( NPC, CHAN_AUTO, G_SoundIndex( va("sound/chars/rancor/snort_%d.wav", Q_irand(1, 2))) );
00940 
00941                         TIMER_Set( NPC, "idlenoise", Q_irand( 2000, 4000 ) );
00942                         AddSoundEvent( NPC, NPC->r.currentOrigin, 384, AEL_DANGER, qfalse );//, qfalse );
00943                 }
00944                 if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
00945                 {
00946                         Rancor_Patrol();
00947                 }
00948                 else
00949                 {
00950                         Rancor_Idle();
00951                 }
00952         }
00953 
00954         NPC_UpdateAngles( qtrue, qtrue );
00955 }

void NPC_BSSniper_Default void   ) 
 

Definition at line 854 of file NPC_AI_Sniper.c.

Referenced by NPC_BehaviorSet_Sniper(), and NPC_BSJedi_Default().

00855 {
00856         if( !NPC->enemy )
00857         {//don't have an enemy, look for one
00858                 NPC_BSSniper_Patrol();
00859         }
00860         else//if ( NPC->enemy )
00861         {//have an enemy
00862                 NPC_BSSniper_Attack();
00863         }
00864 }

void NPC_BSST_Default void   ) 
 

Definition at line 2726 of file NPC_AI_Stormtrooper.c.

References gentity_s::enemy, NPC, NPC_BSST_Attack(), NPC_BSST_Patrol(), NPC_CheckGetNewWeapon(), NPCInfo, qtrue, SCF_FIRE_WEAPON, gNPC_t::scriptFlags, and WeaponThink().

Referenced by NPC_BehaviorSet_Stormtrooper().

02727 {
02728         if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON )
02729         {
02730                 WeaponThink( qtrue );
02731         }
02732         
02733         if( !NPC->enemy )
02734         {//don't have an enemy, look for one
02735                 NPC_BSST_Patrol();
02736         }
02737         else //if ( NPC->enemy )
02738         {//have an enemy
02739                 NPC_CheckGetNewWeapon();
02740                 NPC_BSST_Attack();
02741         }
02742 }

void NPC_BSST_Investigate void   ) 
 

Definition at line 978 of file NPC_AI_Stormtrooper.c.

References AEL_MINOR, AI_GetGroup(), level_locals_t::alertEvents, BS_DEFAULT, BUTTON_WALKING, usercmd_s::buttons, gNPC_t::confusionTime, entityShared_t::currentOrigin, FlyingCreature(), gNPC_t::goalEntity, alertEvent_s::ID, gNPC_t::investigateCount, gNPC_t::investigateDebounceTime, gNPC_t::lastAlertID, level, gNPC_t::localState, LSTATE_INVESTIGATE, LSTATE_NONE, entityShared_t::maxs, entityShared_t::mins, NAV_HitNavGoal(), NPC, NPC_CheckAlertEvents(), NPC_CheckForDanger(), NPC_CheckPlayerTeamStealth(), NPC_MoveToGoal(), NPC_UpdateAngles(), NPCInfo, NULL, gNPC_t::pauseTime, qfalse, qtrue, gentity_s::r, SCF_FIRE_WEAPON, SCF_IGNORE_ALERTS, SCF_LOOK_FOR_ENEMIES, gNPC_t::scriptFlags, SPEECH_COVER, SPEECH_DETECTED, SPEECH_GIVEUP, gNPC_t::tempBehavior, level_locals_t::time, ucmd, UpdateGoal(), and WeaponThink().

Referenced by NPC_BehaviorSet_Stormtrooper().

00979 {
00980         //get group- mainly for group speech debouncing, but may use for group scouting/investigating AI, too
00981         AI_GetGroup( NPC );
00982 
00983         if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON )
00984         {
00985                 WeaponThink( qtrue );
00986         }
00987 
00988         if ( NPCInfo->confusionTime < level.time )
00989         {
00990                 if ( NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES )
00991                 {
00992                         //Look for an enemy
00993                         if ( NPC_CheckPlayerTeamStealth() )
00994                         {
00995                                 //NPCInfo->behaviorState        = BS_HUNT_AND_KILL;//should be auto now
00996                                 ST_Speech( NPC, SPEECH_DETECTED, 0 );
00997                                 NPCInfo->tempBehavior   = BS_DEFAULT;
00998                                 NPC_UpdateAngles( qtrue, qtrue );
00999                                 return;
01000                         }
01001                 }
01002         }
01003 
01004         if ( !(NPCInfo->scriptFlags&SCF_IGNORE_ALERTS) )
01005         {
01006                 int alertEvent = NPC_CheckAlertEvents( qtrue, qtrue, NPCInfo->lastAlertID, qfalse, AEL_MINOR );
01007 
01008                 //There is an event to look at
01009                 if ( alertEvent >= 0 )
01010                 {
01011                         if ( NPCInfo->confusionTime < level.time )
01012                         {
01013                                 if ( NPC_CheckForDanger( alertEvent ) )
01014                                 {//running like hell
01015                                         ST_Speech( NPC, SPEECH_COVER, 0 );//FIXME: flee sound?
01016                                         return;
01017                                 }
01018                         }
01019 
01020                         if ( level.alertEvents[alertEvent].ID != NPCInfo->lastAlertID )
01021                         {
01022                                 NPC_ST_InvestigateEvent( alertEvent, qtrue );
01023                         }
01024                 }
01025         }
01026 
01027         //If we're done looking, then just return to what we were doing
01028         if ( ( NPCInfo->investigateDebounceTime + NPCInfo->pauseTime ) < level.time )
01029         {
01030                 NPCInfo->tempBehavior = BS_DEFAULT;
01031                 NPCInfo->goalEntity = UpdateGoal();
01032                 
01033                 NPC_UpdateAngles( qtrue, qtrue );
01034                 //Say something
01035                 ST_Speech( NPC, SPEECH_GIVEUP, 0 );
01036                 return;
01037         }
01038 
01039         //FIXME: else, look for new alerts
01040 
01041         //See if we're searching for the noise's origin
01042         if ( NPCInfo->localState == LSTATE_INVESTIGATE && (NPCInfo->goalEntity!=NULL) )
01043         {
01044                 //See if we're there
01045                 if ( NAV_HitNavGoal( NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, NPCInfo->goalEntity->r.currentOrigin, 32, FlyingCreature( NPC ) ) == qfalse )
01046                 {
01047                         ucmd.buttons |= BUTTON_WALKING;
01048 
01049                         //Try and move there
01050                         if ( NPC_MoveToGoal( qtrue )  )
01051                         {
01052                                 //Bump our times
01053                                 NPCInfo->investigateDebounceTime        = NPCInfo->investigateCount * 5000;
01054                                 NPCInfo->pauseTime                                      = level.time;
01055 
01056                                 NPC_UpdateAngles( qtrue, qtrue );
01057                                 return;
01058                         }
01059                 }
01060 
01061                 //Otherwise we're done or have given up
01062                 //Say something
01063                 //ST_Speech( NPC, SPEECH_LOOK, 0.33f );
01064                 NPCInfo->localState = LSTATE_NONE;
01065         }
01066 
01067         //Look around
01068         ST_LookAround();
01069 }

void NPC_BSST_Sleep void   ) 
 

Definition at line 447 of file NPC_AI_Stormtrooper.c.

References AEL_DISCOVERED, AEL_MINOR, level_locals_t::alertEvents, g_entities, G_SetEnemy(), gentity_s::health, level, alertEvent_s::level, NPC, NPC_CheckAlertEvents(), NPCInfo, qfalse, qtrue, SCF_LOOK_FOR_ENEMIES, and gNPC_t::scriptFlags.

Referenced by NPC_BehaviorSet_Stormtrooper().

00448 {
00449         int alertEvent = NPC_CheckAlertEvents( qfalse, qtrue, -1, qfalse, AEL_MINOR );//only check sounds since we're alseep!
00450 
00451         //There is an event we heard
00452         if ( alertEvent >= 0 )
00453         {
00454                 //See if it was enough to wake us up
00455                 if ( level.alertEvents[alertEvent].level == AEL_DISCOVERED && (NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES) )
00456                 { //rwwFIXMEFIXME: Care about all clients not just 0
00457                         if ( &g_entities[0] && g_entities[0].health > 0 )
00458                         {
00459                                 G_SetEnemy( NPC, &g_entities[0] );
00460                                 return;
00461                         }
00462                 }
00463 
00464                 //Otherwise just stir a bit
00465                 NPC_ST_SleepShuffle();
00466                 return;
00467         }
00468 }

qboolean NPC_CheckPlayerTeamStealth void   ) 
 

Definition at line 727 of file NPC_AI_Stormtrooper.c.

References gentity_s::client, gclient_s::enemyTeam, ENTITYNUM_WORLD, g_entities, gentity_t, gentity_s::inuse, NPC, NPC_CheckEnemyStealth(), NPC_ValidEnemy(), gclient_s::playerTeam, qboolean, qfalse, and qtrue.

Referenced by ATST_Patrol(), ImperialProbe_Patrol(), Interrogator_Idle(), Mark1_Patrol(), Mark2_Patrol(), NPC_BSGM_Patrol(), NPC_BSGrenadier_Patrol(), NPC_BSSniper_Patrol(), NPC_BSST_Investigate(), NPC_BSST_Patrol(), and NPC_Sentry_Patrol().

00728 {
00729         /*
00730         //NOTENOTE: For now, all stealh checks go against the player, since
00731         //                      he is the main focus.  Squad members and rivals do not
00732         //                      fall into this category and will be ignored.
00733 
00734         NPC_CheckEnemyStealth( &g_entities[0] );        //Change this pointer to assess other entities
00735         */
00736         gentity_t *enemy;
00737         int i;
00738 
00739         for ( i = 0; i < ENTITYNUM_WORLD; i++ )
00740         {
00741                 enemy = &g_entities[i];
00742 
00743                 if (!enemy->inuse)
00744                 {
00745                         continue;
00746                 }
00747 
00748                 if ( enemy && enemy->client && NPC_ValidEnemy( enemy ) && enemy->client->playerTeam == NPC->client->enemyTeam )
00749                 {
00750                         if ( NPC_CheckEnemyStealth( enemy ) )   //Change this pointer to assess other entities
00751                         {
00752                                 return qtrue;
00753                         }
00754                 }
00755         }
00756         return qfalse;
00757 }