void NPC_BehaviorSet_Charmed( int bState ) { switch( bState ) { case BS_FOLLOW_LEADER://# 40: Follow your leader and shoot any enemies you come across NPC_BSFollowLeader(); break; case BS_REMOVE: NPC_BSRemove(); break; case BS_SEARCH: //# 43: Using current waypoint as a base, search the immediate branches of waypoints for enemies NPC_BSSearch(); break; case BS_WANDER: //# 46: Wander down random waypoint paths NPC_BSWander(); break; case BS_FLEE: NPC_BSFlee(); break; default: case BS_DEFAULT://whatever NPC_BSDefault(); break; } }
void NPC_BehaviorSet_Default( int bState ) { switch( bState ) { case BS_ADVANCE_FIGHT://head toward captureGoal, shoot anything that gets in the way NPC_BSAdvanceFight (); break; case BS_SLEEP://Follow a path, looking for enemies NPC_BSSleep (); break; case BS_FOLLOW_LEADER://# 40: Follow your leader and shoot any enemies you come across NPC_BSFollowLeader(); break; case BS_JUMP: //41: Face navgoal and jump to it. NPC_BSJump(); break; case BS_REMOVE: NPC_BSRemove(); break; case BS_SEARCH: //# 43: Using current waypoint as a base, search the immediate branches of waypoints for enemies NPC_BSSearch(); break; case BS_NOCLIP: NPC_BSNoClip(); break; case BS_WANDER: //# 46: Wander down random waypoint paths NPC_BSWander(); break; case BS_FLEE: NPC_BSFlee(); break; case BS_WAIT: NPC_BSWait(); break; case BS_CINEMATIC: NPC_BSCinematic(); break; default: case BS_DEFAULT://whatever NPC_BSDefault(); break; } }
void NPC_BSDefault( void ) { // vec3_t enemyDir; // float enemyDist; // float shootDist; // qboolean enemyFOV = qfalse; // qboolean enemyShotFOV = qfalse; // qboolean enemyPVS = qfalse; // vec3_t enemyHead; // vec3_t muzzle; // qboolean enemyLOS = qfalse; // qboolean enemyCS = qfalse; qboolean move = qtrue; // qboolean shoot = qfalse; if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON ) { WeaponThink( qtrue ); } if ( NPCInfo->scriptFlags & SCF_FORCED_MARCH ) {//being forced to walk if( NPC->client->ps.torsoAnim != TORSO_SURRENDER_START ) { NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_SURRENDER_START, SETANIM_FLAG_HOLD ); } } //look for a new enemy if don't have one and are allowed to look, validate current enemy if have one NPC_CheckEnemy( (NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES), qfalse, qtrue ); if ( !NPC->enemy ) {//still don't have an enemy if ( !(NPCInfo->scriptFlags&SCF_IGNORE_ALERTS) ) {//check for alert events //FIXME: Check Alert events, see if we should investigate or just look at it int alertEvent = NPC_CheckAlertEvents( qtrue, qtrue, -1, qtrue, AEL_DISCOVERED ); //There is an event to look at if ( alertEvent >= 0 && level.alertEvents[alertEvent].ID != NPCInfo->lastAlertID ) {//heard/saw something if ( level.alertEvents[alertEvent].level >= AEL_DISCOVERED && (NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES) ) {//was a big event if ( level.alertEvents[alertEvent].owner && level.alertEvents[alertEvent].owner->client && level.alertEvents[alertEvent].owner->health >= 0 && level.alertEvents[alertEvent].owner->client->playerTeam == NPC->client->enemyTeam ) {//an enemy G_SetEnemy( NPC, level.alertEvents[alertEvent].owner ); } } else {//FIXME: investigate lesser events } } //FIXME: also check our allies' condition? } } if ( NPC->enemy && !(NPCInfo->scriptFlags&SCF_FORCED_MARCH) ) { // just use the stormtrooper attack AI... NPC_CheckGetNewWeapon(); if ( NPC->client->leader && NPCInfo->goalEntity == NPC->client->leader && !trap_ICARUS_TaskIDPending( NPC, TID_MOVE_NAV ) ) { NPC_ClearGoal(); } NPC_BSST_Attack(); return; /* //have an enemy //FIXME: if one of these fails, meaning we can't shoot, do we really need to do the rest? VectorSubtract( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, enemyDir ); enemyDist = VectorNormalize( enemyDir ); enemyDist *= enemyDist; shootDist = NPC_MaxDistSquaredForWeapon(); enemyFOV = InFOV( NPC->enemy, NPC, NPCInfo->stats.hfov, NPCInfo->stats.vfov ); enemyShotFOV = InFOV( NPC->enemy, NPC, 20, 20 ); enemyPVS = gi.inPVS( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ); if ( enemyPVS ) {//in the pvs trace_t tr; CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemyHead ); enemyHead[2] -= Q_flrand( 0.0f, NPC->enemy->maxs[2]*0.5f ); CalcEntitySpot( NPC, SPOT_WEAPON, muzzle ); enemyLOS = NPC_ClearLOS( muzzle, enemyHead ); gi.trace ( &tr, muzzle, vec3_origin, vec3_origin, enemyHead, NPC->s.number, MASK_SHOT ); enemyCS = NPC_EvaluateShot( tr.entityNum, qtrue ); } else {//skip thr 2 traces since they would have to fail enemyLOS = qfalse; enemyCS = qfalse; } if ( enemyCS && enemyShotFOV ) {//can hit enemy if we want NPC->cantHitEnemyCounter = 0; } else {//can't hit NPC->cantHitEnemyCounter++; } if ( enemyCS && enemyShotFOV && enemyDist < shootDist ) {//can shoot shoot = qtrue; if ( NPCInfo->goalEntity == NPC->enemy ) {//my goal is my enemy and I have a clear shot, no need to chase right now move = qfalse; } } else {//don't shoot yet, keep chasing shoot = qfalse; move = qtrue; } //shoot decision if ( !(NPCInfo->scriptFlags&SCF_DONT_FIRE) ) {//try to shoot if ( NPC->enemy ) { if ( shoot ) { if( !(NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here { WeaponThink( qtrue ); } } } } //chase decision if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) {//go after him NPCInfo->goalEntity = NPC->enemy; //FIXME: don't need to chase when have a clear shot and in range? if ( !enemyCS && NPC->cantHitEnemyCounter > 60 ) {//haven't been able to shoot enemy for about 6 seconds, need to do something //FIXME: combat points? Just chase? if ( enemyPVS ) {//in my PVS, just pick a combat point //FIXME: implement } else {//just chase him } } //FIXME: in normal behavior, should we use combat Points? Do we care? Is anyone actually going to ever use this AI? } else if ( NPC->cantHitEnemyCounter > 60 ) {//pick a new one NPC_CheckEnemy( qtrue, qfalse, qtrue ); } if ( enemyPVS && enemyLOS )//&& !enemyShotFOV ) {//have a clear LOS to him//, but not looking at him //Find the desired angles vec3_t angles; GetAnglesForDirection( muzzle, enemyHead, angles ); NPCInfo->desiredYaw = AngleNormalize180( angles[YAW] ); NPCInfo->desiredPitch = AngleNormalize180( angles[PITCH] ); } */ } if ( UpdateGoal() ) {//have a goal if ( !NPC->enemy && NPC->client->leader && NPCInfo->goalEntity == NPC->client->leader && !trap_ICARUS_TaskIDPending( NPC, TID_MOVE_NAV ) ) { NPC_BSFollowLeader(); } else { //set angles if ( (NPCInfo->scriptFlags & SCF_FACE_MOVE_DIR) || NPCInfo->goalEntity != NPC->enemy ) {//face direction of movement, NOTE: default behavior when not chasing enemy NPCInfo->combatMove = qfalse; } else {//face goal.. FIXME: what if have a navgoal but want to face enemy while moving? Will this do that? vec3_t dir, angles; NPCInfo->combatMove = qfalse; VectorSubtract( NPCInfo->goalEntity->r.currentOrigin, NPC->r.currentOrigin, dir ); vectoangles( dir, angles ); NPCInfo->desiredYaw = angles[YAW]; if ( NPCInfo->goalEntity == NPC->enemy ) { NPCInfo->desiredPitch = angles[PITCH]; } } //set movement //override default walk/run behavior //NOTE: redundant, done in NPC_ApplyScriptFlags if ( NPCInfo->scriptFlags & SCF_RUNNING ) { ucmd.buttons &= ~BUTTON_WALKING; } else if ( NPCInfo->scriptFlags & SCF_WALKING ) { ucmd.buttons |= BUTTON_WALKING; } else if ( NPCInfo->goalEntity == NPC->enemy ) { ucmd.buttons &= ~BUTTON_WALKING; } else { ucmd.buttons |= BUTTON_WALKING; } if ( NPCInfo->scriptFlags & SCF_FORCED_MARCH ) {//being forced to walk //if ( g_crosshairEntNum != NPC->s.number ) if (!NPC_SomeoneLookingAtMe(NPC)) {//don't walk if player isn't aiming at me move = qfalse; } } if ( move ) { //move toward goal NPC_MoveToGoal( qtrue ); } } } else if ( !NPC->enemy && NPC->client->leader ) { NPC_BSFollowLeader(); } //update angles NPC_UpdateAngles( qtrue, qtrue ); }
void NPC_BehaviorSet_Default( int bState ) { switch( bState ) { case BS_WAIT://Do abolutely nothing NPC_BSWait (); break; case BS_IDLE://Stand around, move if have a goal, update angles NPC_BSIdle (); break; case BS_ROAM://Roam around, collect stuff NPC_BSRoam (); break; case BS_WALK://Walk toward their goals NPC_BSWalk (); break; case BS_CROUCH://Crouch-Walk toward their goals NPC_BSCrouch (); break; case BS_RUN://Run toward their goals NPC_BSRun (); break; case BS_STAND_AND_SHOOT://Stay in one spot and shoot- duck when neccesary NPC_BSStandAndShoot (); break; case BS_STAND_GUARD://Wait around for an enemy NPC_BSStandGuard (); break; case BS_PATROL://Follow a path, looking for enemies NPC_BSPatrol (); break; case BS_HUNT_AND_KILL://Track down enemies and kill them NPC_BSHuntAndKill (); break; case BS_EVADE://Run from enemies NPC_BSEvade (); break; case BS_EVADE_AND_SHOOT://Run from enemies, shoot them if they hit you NPC_BSEvadeAndShoot (); break; case BS_RUN_AND_SHOOT://Run to your goal and shoot enemy when possible NPC_BSRunAndShoot (); break; case BS_DEFEND://Defend an entity or spot? NPC_BSDefend (); break; case BS_COMBAT://Attack, evade, use cover, move about, etc. Full combat AI - id Bot code NPC_BSCombat (); break; case BS_MEDIC://Go for lowest health buddy, hide and heal him. NPC_BSMedic (); break; case BS_MEDIC_COMBAT: //27: Run to and heal people to a certain level then go back to hiding spot NPC_BSMedicCombat (); break; case BS_MEDIC_HIDE: //28: Stay in hiding spot and wait for others to come to you NPC_BSMedicHide (); break; case BS_TAKECOVER://Find nearest cover from enemies NPC_BSTakeCover (); break; case BS_GET_AMMO://Go get some ammo NPC_BSGetAmmo (); break; case BS_ADVANCE_FIGHT://head toward captureGoal, shoot anything that gets in the way NPC_BSAdvanceFight (); break; case BS_FACE://Face a direction NPC_BSFace (); break; case BS_FORMATION://Maintain a formation NPC_BSFormation (); break; case BS_MOVE: NPC_BSMove(); break; case BS_WAITHEAL: //24: Do nothing until health > 75 NPC_BSWaitHeal(); break; case BS_SHOOT: //25: shoot straight ahead NPC_BSShoot(); break; case BS_SNIPER: //26: wait for a good shot NPC_BSSniper(); break; case BS_POINT_AND_SHOOT: NPC_BSPointShoot(qtrue); break; case BS_FACE_ENEMY: NPC_BSPointShoot(qfalse); break; case BS_INVESTIGATE: //29: NPC_BSInvestigate(); break; case BS_SLEEP://Follow a path, looking for enemies NPC_BSSleep (); break; case BS_SAY://36: Turn to sayTarg, use talk anim, say your sayString (look up string in your sounds table), exit tempBState when sound finished (anim of mouth should be timed to length of sound as well) NPC_BSSay (); break; case BS_AIM://37: Turn head and torso to facing, keep feet in place if you can NPC_BSFace (); break; case BS_LOOK://38: Turn head only to facing, keep torso and head in place if you can NPC_BSFace (); break; case BS_POINT_COMBAT://39: Head toward closest empty point_combat and shoot from there NPC_BSPointCombat (); break; case BS_FOLLOW_LEADER://# 40: Follow your leader and shoot any enemies you come across NPC_BSFollowLeader(); break; case BS_JUMP: //41: Face navgoal and jump to it. NPC_BSJump(); break; case BS_REMOVE: NPC_BSRemove(); break; case BS_SEARCH: //# 43: Using current waypoint as a base, search the immediate branches of waypoints for enemies NPC_BSSearch(); break; case BS_FLY: //# 44: Moves around without gravity NPC_BSFly(); break; case BS_NOCLIP: NPC_BSNoClip(); break; case BS_WANDER: //# 46: Wander down random waypoint paths NPC_BSWander(); break; case BS_FACE_LEADER://# 47: Keep facing the leader NPC_BSFaceLeader(); break; default: case BS_DEFAULT://whatever NPC_BSIdle (); break; } }