void NPC_Respond( gentity_t *self, int userNum )
{
	int event;

	if ( self->NPC->behaviorState == BS_FORMATION )
	{
		event = Q_irand(EV_MISSION1, EV_MISSION3);
	}
	else
	{
		if ( Q_irand( 0, 1 ) )
		{
			event = Q_irand(EV_RESPOND1, EV_RESPOND3);
		}
		else
		{
			event = Q_irand(EV_BUSY1, EV_BUSY3);
		}

		if( !Q_irand( 0, 1 ) )
		{//set looktarget to them for a second or two
			NPC_TempLookTarget( self, userNum, 1000, 3000 );
		}
	}

	G_AddVoiceEvent( self, event, 3000 );
}
Example #2
0
void NPC_Respond( gentity_t *self, int userNum )
{
	int event = -1;
	/*

	if ( Q_irand( 0, 1 ) )
	{
		event = Q_irand(EV_RESPOND1, EV_RESPOND3);
	}
	else
	{
		event = Q_irand(EV_BUSY1, EV_BUSY3);
	}
	*/

	if ( !Q_irand( 0, 1 ) )
	{//set looktarget to them for a second or two
		NPC_TempLookTarget( self, userNum, 1000, 3000 );
	}

	//some last-minute hacked in responses
	switch ( self->client->NPC_class )
	{
	case CLASS_JAN:
		if ( self->enemy )
		{
			if ( !Q_irand( 0, 2 ) )
			{
				event = Q_irand( EV_CHASE1, EV_CHASE3 );
			}
			else if ( Q_irand( 0, 1 ) )
			{
				event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 );
			}
			else
			{
				event = Q_irand( EV_COVER1, EV_COVER5 );
			}
		}
		else if ( !Q_irand( 0, 2 ) )
		{
			event = EV_SUSPICIOUS4;
		}
		else if ( !Q_irand( 0, 1 ) )
		{
			event = EV_SOUND1;
		}
		else
		{
			event = EV_CONFUSE1;
		}
		break;
	case CLASS_LANDO:
		if ( self->enemy )
		{
			if ( !Q_irand( 0, 2 ) )
			{
				event = Q_irand( EV_CHASE1, EV_CHASE3 );
			}
			else if ( Q_irand( 0, 1 ) )
			{
				event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 );
			}
			else
			{
				event = Q_irand( EV_COVER1, EV_COVER5 );
			}
		}
		else if ( !Q_irand( 0, 6 ) )
		{
			event = EV_SIGHT2;
		}
		else if ( !Q_irand( 0, 5 ) )
		{
			event = EV_GIVEUP4;
		}
		else if ( Q_irand( 0, 4 ) > 1 )
		{
			event = Q_irand( EV_SOUND1, EV_SOUND3 );
		}
		else
		{
			event = Q_irand( EV_JDETECTED1, EV_JDETECTED2 );
		}
		break;
	case CLASS_LUKE:
		if ( self->enemy )
		{
			event = EV_COVER1;
		}
		else
		{
			event = Q_irand( EV_SOUND1, EV_SOUND3 );
		}
		break;
	case CLASS_JEDI:
	case CLASS_KYLE:
		if ( !self->enemy )
		{
			/*
			if ( !(self->svFlags&SVF_IGNORE_ENEMIES)
				&& (self->NPC->scriptFlags&SCF_LOOK_FOR_ENEMIES)
				&& self->client->enemyTeam == TEAM_ENEMY )
			{
				event = Q_irand( EV_ANGER1, EV_ANGER3 );
			}
			else
			*/
			{
				event = Q_irand( EV_CONFUSE1, EV_CONFUSE3 );
			}
		}
		break;
	case CLASS_PRISONER:
		if ( self->enemy )
		{
			if ( Q_irand( 0, 1 ) )
			{
				event = Q_irand( EV_CHASE1, EV_CHASE3 );
			}
			else
			{
				event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 );
			}
		}
		else
		{
			event = Q_irand( EV_SOUND1, EV_SOUND3 );
		}
		break;
	case CLASS_REBEL:
		if ( self->enemy )
		{
			if ( !Q_irand( 0, 2 ) )
			{
				event = Q_irand( EV_CHASE1, EV_CHASE3 );
			}
			else
			{
				event = Q_irand( EV_DETECTED1, EV_DETECTED5 );
			}
		}
		else
		{
			event = Q_irand( EV_SOUND1, EV_SOUND3 );
		}
		break;
	case CLASS_BESPIN_COP:
		if ( !Q_stricmp( "bespincop", self->NPC_type ) )
		{//variant 1
			if ( self->enemy )
			{
				if ( Q_irand( 0, 9 ) > 6 )
				{
					event = Q_irand( EV_CHASE1, EV_CHASE3 );
				}
				else if ( Q_irand( 0, 6 ) > 4 )
				{
					event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 );
				}
				else
				{
					event = Q_irand( EV_COVER1, EV_COVER5 );
				}
			}
			else if ( !Q_irand( 0, 3 ) )
			{
				event = Q_irand( EV_SIGHT2, EV_SIGHT3 );
			}
			else if ( !Q_irand( 0, 1 ) )
			{
				event = Q_irand( EV_SOUND1, EV_SOUND3 );
			}
			else if ( !Q_irand( 0, 2 ) )
			{
				event = EV_LOST1;
			}
			else if ( !Q_irand( 0, 1 ) )
			{
				event = EV_ESCAPING2;
			}
			else
			{
				event = EV_GIVEUP4;
			}
		}
		else
		{//variant2
			if ( self->enemy )
			{
				if ( Q_irand( 0, 9 ) > 6 )
				{
					event = Q_irand( EV_CHASE1, EV_CHASE3 );
				}
				else if ( Q_irand( 0, 6 ) > 4 )
				{
					event = Q_irand( EV_OUTFLANK1, EV_OUTFLANK2 );
				}
				else
				{
					event = Q_irand( EV_COVER1, EV_COVER5 );
				}
			}
			else if ( !Q_irand( 0, 3 ) )
			{
				event = Q_irand( EV_SIGHT1, EV_SIGHT2 );
			}
			else if ( !Q_irand( 0, 1 ) )
			{
				event = Q_irand( EV_SOUND1, EV_SOUND3 );
			}
			else if ( !Q_irand( 0, 2 ) )
			{
				event = EV_LOST1;
			}
			else if ( !Q_irand( 0, 1 ) )
			{
				event = EV_GIVEUP3;
			}
			else
			{
				event = EV_CONFUSE1;
			}
		}
		break;
	case CLASS_R2D2:				// droid
		G_Sound(self, G_SoundIndex(va("sound/chars/r2d2/misc/r2d2talk0%d.wav",Q_irand(1, 3))));
		break;
	case CLASS_R5D2:				// droid
		G_Sound(self, G_SoundIndex(va("sound/chars/r5d2/misc/r5talk%d.wav",Q_irand(1, 4))));
		break;
	case CLASS_MOUSE:				// droid
		G_Sound(self, G_SoundIndex(va("sound/chars/mouse/misc/mousego%d.wav",Q_irand(1, 3))));
		break;
	case CLASS_GONK:				// droid
		G_Sound(self, G_SoundIndex(va("sound/chars/gonk/misc/gonktalk%d.wav",Q_irand(1, 2))));
		break;
	case CLASS_JAWA:
		G_SoundOnEnt(self, CHAN_VOICE, va("sound/chars/jawa/misc/chatter%d.wav",Q_irand(1, 6)) );
		if ( self->NPC )
		{
			self->NPC->blockedSpeechDebounceTime = level.time + 2000;
		}
		break;
	default:
		break;
	}

	if ( event != -1 )
	{
		//hack here because we reuse some "combat" and "extra" sounds
		qboolean addFlag = (qboolean)((self->NPC->scriptFlags&SCF_NO_COMBAT_TALK) != 0);
		self->NPC->scriptFlags &= ~SCF_NO_COMBAT_TALK;

		G_AddVoiceEvent( self, event, 3000 );

		if ( addFlag )
		{
			self->NPC->scriptFlags |= SCF_NO_COMBAT_TALK;
		}
	}
}
Example #3
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;
				}
			}
		}
	}
}