void NPC_HandleAIFlags (void) { //FIXME: make these flags checks a function call like NPC_CheckAIFlagsAndTimers if ( NPCInfo->aiFlags & NPCAI_LOST ) {//Print that you need help! //FIXME: shouldn't remove this just yet if cg_draw needs it NPCInfo->aiFlags &= ~NPCAI_LOST; if ( NPCInfo->goalEntity && NPCInfo->goalEntity == NPC->enemy ) {//We can't nav to our enemy //Drop enemy and see if we should search for him NPC_LostEnemyDecideChase(); } } //been told to play a victory sound after a delay if ( NPCInfo->greetingDebounceTime && NPCInfo->greetingDebounceTime < level.time ) { G_AddVoiceEvent( NPC, Q_irand(EV_VICTORY1, EV_VICTORY3), Q_irand( 2000, 4000 ) ); NPCInfo->greetingDebounceTime = 0; } if ( NPCInfo->ffireCount > 0 ) { if ( NPCInfo->ffireFadeDebounce < level.time ) { NPCInfo->ffireCount--; NPCInfo->ffireFadeDebounce = level.time + 3000; } } if ( d_patched.integer ) {//use patch-style navigation if ( NPCInfo->consecutiveBlockedMoves > 20 ) {//been stuck for a while, try again? NPCInfo->consecutiveBlockedMoves = 0; } } }
void NPC_BSRunAndShoot (void) { /*if(NPC->playerTeam && NPC->enemyTeam) { //FIXME: don't realize this right away- or else enemies show up and we're standing around if( teamNumbers[NPC->enemyTeam] == 0 ) {//ok, stand guard until we find another enemy //reset our rush counter teamCounter[NPC->playerTeam] = 0; NPCInfo->tempBehavior = BS_STAND_GUARD; NPC_BSStandGuard(); return; } }*/ //NOTE: are we sure we want ALL run and shoot people to move this way? //Shouldn't it check to see if we have an enemy and our enemy is our goal?! //Moved that check into NPC_MoveToGoal //NPCInfo->combatMove = qtrue; NPC_CheckEnemy( qtrue, qfalse, qtrue ); if ( NPCInfo->duckDebounceTime > level.time ) // && NPCInfo->hidingGoal ) { ucmd.upmove = -127; if ( NPC->enemy ) { NPC_CheckCanAttack( 1.0, qfalse ); } return; } if ( NPC->enemy ) { int monitor = NPC->cantHitEnemyCounter; NPC_StandTrackAndShoot( NPC, qfalse );//(NPCInfo->hidingGoal != NULL) ); if ( !(ucmd.buttons & BUTTON_ATTACK) && ucmd.upmove >= 0 && NPC->cantHitEnemyCounter > monitor ) {//not crouching and not firing vec3_t vec; VectorSubtract( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, vec ); vec[2] = 0; if ( VectorLength( vec ) > 128 || NPC->cantHitEnemyCounter >= 10 ) {//run at enemy if too far away //The cantHitEnemyCounter getting high has other repercussions //100 (10 seconds) will make you try to pick a new enemy... //But we're chasing, so we clamp it at 50 here if ( NPC->cantHitEnemyCounter > 60 ) { NPC->cantHitEnemyCounter = 60; } if ( NPC->cantHitEnemyCounter >= (NPCInfo->stats.aggression+1) * 10 ) { NPC_LostEnemyDecideChase(); } //chase and face ucmd.angles[YAW] = 0; ucmd.angles[PITCH] = 0; NPCInfo->goalEntity = NPC->enemy; NPCInfo->goalRadius = 12; //NAV_ClearLastRoute(NPC); NPC_MoveToGoal( qtrue ); NPC_UpdateAngles(qtrue, qtrue); } else { //FIXME: this could happen if they're just on the other side //of a thin wall or something else blocking out shot. That //would make us just stand there and not go around it... //but maybe it's okay- might look like we're waiting for //him to come out...? //Current solution: runs around if cantHitEnemyCounter gets //to 10 (1 second). } } else {//Clear the can't hit enemy counter here NPC->cantHitEnemyCounter = 0; } } else { if ( NPCInfo->tempBehavior == BS_HUNT_AND_KILL ) {//lost him, go back to what we were doing before NPCInfo->tempBehavior = BS_DEFAULT; return; } // NPC_BSRun();//only moves if we have a goal } }
void NPC_HandleAIFlags (void) { //FIXME: make these flags checks a function call like NPC_CheckAIFlagsAndTimers if ( NPCInfo->aiFlags & NPCAI_LOST ) {//Print that you need help! //FIXME: shouldn't remove this just yet if cg_draw needs it NPCInfo->aiFlags &= ~NPCAI_LOST; /* if ( showWaypoints ) { Q3_DebugPrint(WL_WARNING, "%s can't navigate to target %s (my wp: %d, goal wp: %d)\n", NPC->targetname, NPCInfo->goalEntity->targetname, NPC->waypoint, NPCInfo->goalEntity->waypoint ); } */ if ( NPCInfo->goalEntity && NPCInfo->goalEntity == NPC->enemy ) {//We can't nav to our enemy //Drop enemy and see if we should search for him NPC_LostEnemyDecideChase(); } } //MRJ Request: /* if ( NPCInfo->aiFlags & NPCAI_GREET_ALLIES && !NPC->enemy )//what if "enemy" is the greetEnt? {//If no enemy, look for teammates to greet //FIXME: don't say hi to the same guy over and over again. if ( NPCInfo->greetingDebounceTime < level.time ) {//Has been at least 2 seconds since we greeted last if ( !NPCInfo->greetEnt ) {//Find a teammate whom I'm facing and who is facing me and within 128 NPCInfo->greetEnt = NPC_PickAlly( qtrue, 128, qtrue, qtrue ); } if ( NPCInfo->greetEnt && !Q_irand(0, 5) ) {//Start greeting someone qboolean greeted = qfalse; //TODO: If have a greetscript, run that instead? //FIXME: make them greet back? if( !Q_irand( 0, 2 ) ) {//Play gesture anim (press gesture button?) greeted = qtrue; NPC_SetAnim( NPC, SETANIM_TORSO, Q_irand( BOTH_GESTURE1, BOTH_GESTURE3 ), SETANIM_FLAG_NORMAL|SETANIM_FLAG_HOLD ); //NOTE: play full-body gesture if not moving? } if( !Q_irand( 0, 2 ) ) {//Play random voice greeting sound greeted = qtrue; //FIXME: need NPC sound sets //G_AddVoiceEvent( NPC, Q_irand(EV_GREET1, EV_GREET3), 2000 ); } if( !Q_irand( 0, 1 ) ) {//set looktarget to them for a second or two greeted = qtrue; NPC_TempLookTarget( NPC, NPCInfo->greetEnt->s.number, 1000, 3000 ); } if ( greeted ) {//Did at least one of the things above //Don't greet again for 2 - 4 seconds NPCInfo->greetingDebounceTime = level.time + Q_irand( 2000, 4000 ); NPCInfo->greetEnt = NULL; } } } } */ //been told to play a victory sound after a delay if ( NPCInfo->greetingDebounceTime && NPCInfo->greetingDebounceTime < level.time ) { G_AddVoiceEvent( NPC, Q_irand(EV_VICTORY1, EV_VICTORY3), Q_irand( 2000, 4000 ) ); NPCInfo->greetingDebounceTime = 0; } if ( NPCInfo->ffireCount > 0 ) { if ( NPCInfo->ffireFadeDebounce < level.time ) { NPCInfo->ffireCount--; //Com_Printf( "drop: %d < %d\n", NPCInfo->ffireCount, 3+((2-g_spSkill.integer)*2) ); NPCInfo->ffireFadeDebounce = level.time + 3000; } } if ( d_patched.integer ) {//use patch-style navigation if ( NPCInfo->consecutiveBlockedMoves > 20 ) {//been stuck for a while, try again? NPCInfo->consecutiveBlockedMoves = 0; } } }
void NPC_HandleAIFlags (void) { //FIXME: make these flags checks a function call like NPC_CheckAIFlagsAndTimers if ( NPCInfo->aiFlags & NPCAI_LOST ) {//Print that you need help! //FIXME: shouldn't remove this just yet if cg_draw needs it NPCInfo->aiFlags &= ~NPCAI_LOST; /* if ( showWaypoints ) { Q3_DebugPrint(WL_WARNING, "%s can't navigate to target %s (my wp: %d, goal wp: %d)\n", NPC->targetname, NPCInfo->goalEntity->targetname, NPC->waypoint, NPCInfo->goalEntity->waypoint ); } */ if ( NPCInfo->goalEntity && NPCInfo->goalEntity == NPC->enemy ) {//We can't nav to our enemy //Drop enemy and see if we should search for him NPC_LostEnemyDecideChase(); } } if ( NPCInfo->aiFlags & NPCAI_AWAITING_COMM ) { if(NPCInfo->commWaitTime < level.time) { //FIXME: we shouldn't assume team_leader, we should remember who sent this hail! NPC_SetSayState(NPC, NPC->client->team_leader, Q_irand(SAY_BADHAIL1, SAY_BADHAIL4)); NPCInfo->aiFlags &= ~NPCAI_AWAITING_COMM; } } /* NPCInfo->canShove = qfalse; //flag never gets set in current nav implementation if (NPCInfo->aiFlags & NPCAI_BLOCKED) { NPCInfo->consecutiveBlockedMoves++; NPCInfo->blockedDebounceTime = level.time + 1000;//Remember you were blocked for a whole second //If totally blocked, should we see if we can jump the obstacle? if(NPCInfo->blockingEntNum == ENTITYNUM_WORLD)//WORLD {//Can't go anywhere G_ActivateBehavior( NPC, BSET_STUCK); //If you're in formation, what do we do here? } else { gentity_t *blocker = &g_entities[NPCInfo->blockingEntNum]; if( NPCInfo->consecutiveBlockedMoves > 10 ) {//Okay, shove them out of the way! if(NPCInfo->shoveCount > 3) {//Already tried shoving 4 times, just stand here NPCInfo->canShove = qfalse; } else { NPCInfo->canShove = qtrue; } } if(blocker->client && blocker->client->playerTeam == NPC->client->playerTeam) {//Should we ask it to get out of the way? //FIXME: NPC_SetSayBState(NPC, blocker, Q_irand(SAY_MOVEIT1, SAY_MOVEIT4);// ? if(NPCInfo->blockedSpeechDebounceTime < level.time) { if ( NPC->behaviorSet[BSET_BLOCKED] ) { G_ActivateBehavior( NPC, BSET_BLOCKED); } else { G_AddVoiceEvent( NPC, Q_irand(EV_BLOCKED1, EV_BLOCKED3), 0 ); } #ifdef _DEBUG //gi.Printf( "%s: 'Hey, %s, move it!'\n", NPC->targetname, blocker->targetname ); #endif //NPCInfo->blockedSpeechDebounceTime = level.time + 10000;//FIXME: make a define //Ok, need to make it get out of the way... } } else if((blocker->client || blocker->takedamage) && blocker->health > 0 && blocker->health < 200 ) {//Attack it!? Set enemy and temp behavior? Hmm... //Careful, what if it's explosive? G_SetEnemy( NPC, blocker ); if( NPCInfo->consecutiveBlockedMoves == 30 ) {//Blocked for three seconds straight G_ActivateBehavior( NPC, BSET_BLOCKED); } } } } else if(NPCInfo->blockedDebounceTime < level.time) {//Only clear if haven't been blocked for a whole second NPCInfo->consecutiveBlockedMoves = 0; NPCInfo->shoveCount = 0; } if(NPCInfo->shoveDebounce < level.time) {//We have shoved for 1 second at least NPCInfo->lastShoveDir = 0.0f; } //NAV_ClearBlockedInfo(NPC); */ //MRJ Request: if ( NPCInfo->aiFlags & NPCAI_GREET_ALLIES && !NPC->enemy )//what if "enemy" is the greetEnt? {//If no enemy, look for teammates to greet //FIXME: don't say hi to the same guy over and over again. if ( NPCInfo->greetingDebounceTime < level.time ) {//Has been at least 2 seconds since we greeted last if ( !NPCInfo->greetEnt ) {//Find a teammate whom I'm facing and who is facing me and within 128 NPCInfo->greetEnt = NPC_PickAlly( qtrue, 128, qtrue, qtrue ); } if ( NPCInfo->greetEnt && !Q_irand(0, 5) ) {//Start greeting someone qboolean greeted = qfalse; //TODO: If have a greetscript, run that instead? //FIXME: make them greet back? if( !Q_irand( 0, 2 ) ) {//Play gesture anim (press gesture button?) greeted = qtrue; NPC_SetAnim( NPC, SETANIM_TORSO, Q_irand( BOTH_GESTURE1, BOTH_GESTURE3 ), SETANIM_FLAG_NORMAL|SETANIM_FLAG_HOLD ); //NOTE: play full-body gesture if not moving? } if( !Q_irand( 0, 2 ) ) {//Play random voice greeting sound greeted = qtrue; //FIXME: need NPC sound sets G_AddVoiceEvent( NPC, Q_irand(EV_GREET1, EV_GREET3), 2000 ); } if( !Q_irand( 0, 1 ) ) {//set looktarget to them for a second or two greeted = qtrue; NPC_TempLookTarget( NPC, NPCInfo->greetEnt->s.number, 1000, 3000 ); } if ( greeted ) {//Did at least one of the things above //Don't greet again for 2 - 4 seconds NPCInfo->greetingDebounceTime = level.time + Q_irand( 2000, 4000 ); NPCInfo->greetEnt = NULL; } } } } }