Exemplo n.º 1
0
qboolean NPC_FindEnemy( qboolean checkAlerts )
{
	gentity_t *newenemy;

	//We're ignoring all enemies for now
	//if( NPC->svFlags & SVF_IGNORE_ENEMIES )
	if (0) //rwwFIXMEFIXME: support for flag
	{
		G_ClearEnemy( NPC );
		return qfalse;
	}

	//we can't pick up any enemies for now
	if( NPCInfo->confusionTime > level.time )
	{
		return qfalse;
	}

	//Don't want a new enemy
	//rwwFIXMEFIXME: support for locked enemy
	//if ( ( ValidEnemy( NPC->enemy ) ) && ( NPC->svFlags & SVF_LOCKEDENEMY ) )
	//	return qtrue;

	//See if the player is closer than our current enemy
	if ( NPC_CheckPlayerDistance() )
	{
		return qtrue;
	}

	//Otherwise, turn off the flag
//	NPC->svFlags &= ~SVF_LOCKEDENEMY;
	//See if the player is closer than our current enemy
	if ( NPC->client->NPC_class != CLASS_RANCOR 
		&& NPC->client->NPC_class != CLASS_WAMPA
		//&& NPC->client->NPC_class != CLASS_SAND_CREATURE
		&& NPC_CheckPlayerDistance() )
	{//rancors, wampas & sand creatures don't care if player is closer, they always go with closest
		return qtrue;
	}

	//If we've gotten here alright, then our target it still valid
	if ( NPC_ValidEnemy( NPC->enemy ) )
		return qtrue;

	newenemy = NPC_PickEnemyExt( checkAlerts );

	//if we found one, take it as the enemy
	if( NPC_ValidEnemy( newenemy ) )
	{
		G_SetEnemy( NPC, newenemy );
		return qtrue;
	}

	return qfalse;
}
Exemplo n.º 2
0
qboolean NPC_FindEnemy( qboolean checkAlerts = qfalse )
{
	//We're ignoring all enemies for now
	if( NPC->svFlags & SVF_IGNORE_ENEMIES )
	{
		G_ClearEnemy( NPC );
		return qfalse;
	}

	//we can't pick up any enemies for now
	if( NPCInfo->confusionTime > level.time )
	{
		return qfalse;
	}

	//Don't want a new enemy
	if ( ( ValidEnemy( NPC->enemy ) ) && ( NPC->svFlags & SVF_LOCKEDENEMY ) )
		return qtrue;

	//See if the player is closer than our current enemy
	if ( NPC_CheckPlayerDistance() )
	{
		return qtrue;
	}

	//Otherwise, turn off the flag
	NPC->svFlags &= ~SVF_LOCKEDENEMY;

	//If we've gotten here alright, then our target it still valid
	if ( NPC_ValidEnemy( NPC->enemy ) )
		return qtrue;

	gentity_t *newenemy = NPC_PickEnemyExt( checkAlerts );

	//if we found one, take it as the enemy
	if( NPC_ValidEnemy( newenemy ) )
	{
		G_SetEnemy( NPC, newenemy );
		return qtrue;
	}

	return qfalse;
}
Exemplo n.º 3
0
int NPC_FindNearestEnemy( gentity_t *ent )
{
	int			iradiusEnts[ MAX_RADIUS_ENTS ];
	gentity_t	*radEnt;
	vec3_t		mins, maxs;
	int			nearestEntID = -1;
	float		nearestDist = (float)WORLD_SIZE*(float)WORLD_SIZE;
	float		distance;
	int			numEnts, numChecks = 0;
	int			i;

	//Setup the bbox to search in
	for ( i = 0; i < 3; i++ )
	{
		mins[i] = ent->r.currentOrigin[i] - NPCInfo->stats.visrange;
		maxs[i] = ent->r.currentOrigin[i] + NPCInfo->stats.visrange;
	}

	//Get a number of entities in a given space
	numEnts = trap_EntitiesInBox( mins, maxs, iradiusEnts, MAX_RADIUS_ENTS );

	for ( i = 0; i < numEnts; i++ )
	{
		radEnt = &g_entities[iradiusEnts[i]];
		//Don't consider self
		if ( radEnt == ent )
			continue;

		//Must be valid
		if ( NPC_ValidEnemy( radEnt ) == qfalse )
			continue;

		numChecks++;
		//Must be visible
		if ( NPC_TargetVisible( radEnt ) == qfalse )
			continue;

		distance = DistanceSquared( ent->r.currentOrigin, radEnt->r.currentOrigin );

		//Found one closer to us
		if ( distance < nearestDist )
		{
			nearestEntID = radEnt->s.number;
			nearestDist = distance;
		}
	}

	return nearestEntID;
}
Exemplo n.º 4
0
gentity_t *NPC_PickEnemyExt( qboolean checkAlerts )
{
	//Check for Hazard Team status and remove this check
	/*
	if ( NPC->client->playerTeam != TEAM_STARFLEET )
	{
		//If we've found the player, return it
		if ( NPC_FindPlayer() )
			return &g_entities[0];
	}
	*/

	//If we've asked for the closest enemy
	int entID = NPC_FindNearestEnemy( NPC );

	//If we have a valid enemy, use it
	if ( entID >= 0 )
		return &g_entities[entID];

	if ( checkAlerts )
	{
		int alertEvent = NPC_CheckAlertEvents( qtrue, qtrue, -1, qtrue, AEL_DISCOVERED );

		//There is an event to look at
		if ( alertEvent >= 0 )
		{
			alertEvent_t *event = &level.alertEvents[alertEvent];

			//Don't pay attention to our own alerts
			if ( event->owner == NPC )
				return NULL;

			if ( event->level >= AEL_DISCOVERED )
			{
				//If it's the player, attack him
				if ( event->owner == &g_entities[0] &&  NPC_ValidEnemy(event->owner) ) // UQ1: Errr only if they are enemy...
					return event->owner;

				//If it's on our team, then take its enemy as well  // UQ1: Errr only if they are enemy...
				if ( ( event->owner->client ) && ( event->owner->client->playerTeam == NPC->client->playerTeam ) && NPC_ValidEnemy(event->owner))
					return event->owner->enemy;
			}
		}
	}

	return NULL;
}
Exemplo n.º 5
0
//replaced with SP version.
void NPC_BSHowler_Default( void )
{
	if ( NPC->client->ps.legsAnim != BOTH_GESTURE1 )
	{
		NPC->count = 0;
	}
	//FIXME: if in jump, do damage in front and maybe knock them down?
	if ( !TIMER_Done( NPC, "attacking" ) )
	{
		if ( NPC->enemy )
		{
			//NPC_FaceEnemy( qfalse );
			Howler_Attack( Distance( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ), qfalse );
		}
		else
		{
			//NPC_UpdateAngles( qfalse, qtrue );
			Howler_Attack( 0.0f, qfalse );
		}
		NPC_UpdateAngles( qfalse, qtrue );
		return;
	}

	if ( NPC->enemy )
	{
		if ( NPCInfo->stats.aggression > 0 )
		{
			if ( TIMER_Done( NPC, "aggressionDecay" ) )
			{
				NPCInfo->stats.aggression--;
				TIMER_Set( NPC, "aggressionDecay", 500 );
			}
		}
		//RAFIXME - No fleeing, need to fix this at some point.
		/*
		if ( !TIMER_Done( NPC, "flee" ) 
			&& NPC_BSFlee() )	//this can clear ENEMY
		{//successfully trying to run away
			return;
		}
		*/
		if ( NPC->enemy == NULL)
		{
			NPC_UpdateAngles( qfalse, qtrue );
			return;
		}
		if ( NPCInfo->localState == LSTATE_FLEE )
		{//we were fleeing, now done (either timer ran out or we cannot flee anymore
			if ( NPC_ClearLOS4( NPC->enemy ) )
			{//if enemy is still around, go berzerk
				NPCInfo->localState = LSTATE_BERZERK;
			}
			else
			{//otherwise, lick our wounds?
				NPCInfo->localState = LSTATE_CLEAR;
				TIMER_Set( NPC, "standing", Q_irand( 3000, 10000 ) );
			}
		}
		else if ( NPCInfo->localState == LSTATE_BERZERK )
		{//go nuts!
		}
		else if ( NPCInfo->stats.aggression >= Q_irand( 75, 125 ) )
		{//that's it, go nuts!
			NPCInfo->localState = LSTATE_BERZERK;
		}
		else if ( !TIMER_Done( NPC, "retreating" ) )
		{//trying to back off
			NPC_FaceEnemy( qtrue );
			if ( NPC->client->ps.speed > NPCInfo->stats.walkSpeed )
			{
				NPC->client->ps.speed = NPCInfo->stats.walkSpeed;
			}
			ucmd.buttons |= BUTTON_WALKING;
			if ( Distance( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) < HOWLER_RETREAT_DIST )
			{//enemy is close
				vec3_t moveDir;
				AngleVectors( NPC->r.currentAngles, moveDir, NULL, NULL );
				VectorScale( moveDir, -1, moveDir );
				if ( !NAV_DirSafe( NPC, moveDir, 8 ) )
				{//enemy is backing me up against a wall or ledge!  Start to get really mad!
					NPCInfo->stats.aggression += 2;
				}
				else
				{//back off
					ucmd.forwardmove = -127;
				}
				//enemy won't leave me alone, get mad...
				NPCInfo->stats.aggression++;
			}
			return;
		}
		else if ( TIMER_Done( NPC, "standing" ) )
		{//not standing around
			if ( !(NPCInfo->last_ucmd.forwardmove)
				&& !(NPCInfo->last_ucmd.rightmove) )
			{//stood last frame
				if ( TIMER_Done( NPC, "walking" ) 
					&& TIMER_Done( NPC, "running" ) )
				{//not walking or running
					if ( Q_irand( 0, 2 ) )
					{//run for a while
						TIMER_Set( NPC, "walking", Q_irand( 4000, 8000 ) );
					}
					else
					{//walk for a bit
						TIMER_Set( NPC, "running", Q_irand( 2500, 5000 ) );
					}
				}
			}
			else if ( (NPCInfo->last_ucmd.buttons&BUTTON_WALKING) )
			{//walked last frame
				if ( TIMER_Done( NPC, "walking" ) )
				{//just finished walking
					if ( Q_irand( 0, 5 ) || DistanceSquared( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) < MAX_DISTANCE_SQR )
					{//run for a while
						TIMER_Set( NPC, "running", Q_irand( 4000, 20000 ) );
					}
					else
					{//stand for a bit
						TIMER_Set( NPC, "standing", Q_irand( 2000, 6000 ) );
					}
				}
			}
			else
			{//ran last frame
				if ( TIMER_Done( NPC, "running" ) )
				{//just finished running
					if ( Q_irand( 0, 8 ) || DistanceSquared( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) < MAX_DISTANCE_SQR )
					{//walk for a while
						TIMER_Set( NPC, "walking", Q_irand( 3000, 10000 ) );
					}
					else
					{//stand for a bit
						TIMER_Set( NPC, "standing", Q_irand( 2000, 6000 ) );
					}
				}
			}
		}
		if ( NPC_ValidEnemy( NPC->enemy ) == qfalse )
		{
			TIMER_Remove( NPC, "lookForNewEnemy" );//make them look again right now
			if ( !NPC->enemy->inuse || level.time - NPC->enemy->s.time > Q_irand( 10000, 15000 ) )
			{//it's been a while since the enemy died, or enemy is completely gone, get bored with him
				NPC->enemy = NULL;
				Howler_Patrol();
				NPC_UpdateAngles( qtrue, qtrue );
				return;
			}
		}
		if ( TIMER_Done( NPC, "lookForNewEnemy" ) )
		{
			gentity_t *sav_enemy = NPC->enemy;//FIXME: what about NPC->lastEnemy?
			gentity_t *newEnemy;
			NPC->enemy = NULL;
			newEnemy = NPC_CheckEnemy( (qboolean)(NPCInfo->confusionTime < level.time), qfalse, qfalse );
			NPC->enemy = sav_enemy;
			if ( newEnemy && newEnemy != sav_enemy )
			{//picked up a new enemy!
				NPC->lastEnemy = NPC->enemy;
				G_SetEnemy( NPC, newEnemy );
				if ( NPC->enemy != NPC->lastEnemy )
				{//clear this so that we only sniff the player the first time we pick them up
					//RACC - this doesn't appear to get used for Howlers
					//NPC->useDebounceTime = 0;
				}
				//hold this one for at least 5-15 seconds
				TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
			}
			else
			{//look again in 2-5 secs
				TIMER_Set( NPC, "lookForNewEnemy", Q_irand( 2000, 5000 ) );
			}
		}
		Howler_Combat();
		if ( TIMER_Done( NPC, "speaking" ) )
		{
			if ( !TIMER_Done( NPC, "standing" )
				|| !TIMER_Done( NPC, "retreating" ))
			{
				G_SoundOnEnt( NPC, CHAN_VOICE, va( "sound/chars/howler/idle_hiss%d.mp3", Q_irand( 1, 2 ) ) );
			}
			else if ( !TIMER_Done( NPC, "walking" ) 
				|| NPCInfo->localState == LSTATE_FLEE )
			{
				G_SoundOnEnt( NPC, CHAN_VOICE, va( "sound/chars/howler/howl_talk%d.mp3", Q_irand( 1, 5 ) ) );
			}
			else
			{
				G_SoundOnEnt( NPC, CHAN_VOICE, va( "sound/chars/howler/howl_yell%d.mp3", Q_irand( 1, 5 ) ) );
			}
			if ( NPCInfo->localState == LSTATE_BERZERK
				|| NPCInfo->localState == LSTATE_FLEE )
			{
				TIMER_Set( NPC, "speaking", Q_irand( 1000, 4000 ) );
			}
			else
			{
				TIMER_Set( NPC, "speaking", Q_irand( 3000, 8000 ) );
			}
		}
		return;
	}
	else
	{
		if ( TIMER_Done( NPC, "speaking" ) )
		{
			if ( !Q_irand( 0, 3 ) )
			{
				G_SoundOnEnt( NPC, CHAN_VOICE, va( "sound/chars/howler/idle_hiss%d.mp3", Q_irand( 1, 2 ) ) );
			}
			else
			{
				G_SoundOnEnt( NPC, CHAN_VOICE, va( "sound/chars/howler/howl_talk%d.mp3", Q_irand( 1, 5 ) ) );
			}
			TIMER_Set( NPC, "speaking", Q_irand( 4000, 12000 ) );
		}
		if ( NPCInfo->stats.aggression > 0 )
		{
			if ( TIMER_Done( NPC, "aggressionDecay" ) )
			{
				NPCInfo->stats.aggression--;
				TIMER_Set( NPC, "aggressionDecay", 200 );
			}
		}
		if ( TIMER_Done( NPC, "standing" ) )
		{//not standing around
			if ( !(NPCInfo->last_ucmd.forwardmove)
				&& !(NPCInfo->last_ucmd.rightmove) )
			{//stood last frame
				if ( TIMER_Done( NPC, "walking" ) 
					&& TIMER_Done( NPC, "running" ) )
				{//not walking or running
					if ( NPCInfo->goalEntity )
					{//have somewhere to go
						if ( Q_irand( 0, 2 ) )
						{//walk for a while
							TIMER_Set( NPC, "walking", Q_irand( 3000, 10000 ) );
						}
						else
						{//run for a bit
							TIMER_Set( NPC, "running", Q_irand( 2500, 5000 ) );
						}
					}
				}
			}
			else if ( (NPCInfo->last_ucmd.buttons&BUTTON_WALKING) )
			{//walked last frame
				if ( TIMER_Done( NPC, "walking" ) )
				{//just finished walking
					if ( Q_irand( 0, 3 ) )
					{//run for a while
						TIMER_Set( NPC, "running", Q_irand( 3000, 6000 ) );
					}
					else
					{//stand for a bit
						TIMER_Set( NPC, "standing", Q_irand( 2500, 5000 ) );
					}
				}
			}
			else
			{//ran last frame
				if ( TIMER_Done( NPC, "running" ) )
				{//just finished running
					if ( Q_irand( 0, 2 ) )
					{//walk for a while
						TIMER_Set( NPC, "walking", Q_irand( 6000, 15000 ) );
					}
					else
					{//stand for a bit
						TIMER_Set( NPC, "standing", Q_irand( 4000, 6000 ) );
					}
				}
			}
		}
		if ( NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES )
		{
			Howler_Patrol();
		}
		else
		{
			Howler_Idle();
		}
	}

	NPC_UpdateAngles( qfalse, qtrue );
}
Exemplo n.º 6
0
qboolean NPC_FindEnemy( qboolean checkAlerts )
{//RACC - checks to see if our enemy is still valid.  Updates if it is not.
	gentity_t *newenemy;

	//[CoOp] SP Code
	//reenabling the IGNORE_ENEMIES flag
	if( NPC->NPC->scriptFlags & SCF_IGNORE_ENEMIES )
	//We're ignoring all enemies for now
	//if( NPC->svFlags & SVF_IGNORE_ENEMIES )
	//if (0) //rwwFIXMEFIXME: support for flag
	//[/CoOp]
	{
		G_ClearEnemy( NPC );
		return qfalse;
	}

	//we can't pick up any enemies for now
	if( NPCInfo->confusionTime > level.time )
	{
		//[CoOp] SP Code
		G_ClearEnemy( NPC );
		//[/CoOp]
		return qfalse;
	}

	//[CoOp] SP Code
	//Don't want a new enemy
	if ( ( ValidEnemy( NPC->enemy ) ) && ( NPC->NPC->aiFlags & NPCAI_LOCKEDENEMY ) )
		return qtrue;
	
	//See if the player is closer than our current enemy
	if ( NPC->client->NPC_class != CLASS_RANCOR 
		&& NPC->client->NPC_class != CLASS_WAMPA
		&& NPC->client->NPC_class != CLASS_SAND_CREATURE
		&& NPC_CheckPlayerDistance() )
	{//rancors, wampas & sand creatures don't care if player is closer, they always go with closest
		return qtrue;
	}
	/* This shouldn't be here. SP Code
	//See if the player is closer than our current enemy
	if ( NPC_CheckPlayerDistance() )
	{
		return qtrue;
	}*/
	

	//Otherwise, turn off the flag since if we have a locked enemy at this point,
	//the enemy is invalid.
	NPC->NPC->aiFlags &= ~NPCAI_LOCKEDENEMY;
//	NPC->svFlags &= ~SVF_LOCKEDENEMY;
	/* Moved up.  SP Code
	//See if the player is closer than our current enemy
	if ( NPC->client->NPC_class != CLASS_RANCOR 
		&& NPC->client->NPC_class != CLASS_WAMPA
		//&& NPC->client->NPC_class != CLASS_SAND_CREATURE
		&& NPC_CheckPlayerDistance() )
	{//rancors, wampas & sand creatures don't care if player is closer, they always go with closest
		return qtrue;
	}
	*/
	//[/CoOp]

	//If we've gotten here alright, then our target it still valid
	if ( NPC_ValidEnemy( NPC->enemy ) )
		return qtrue;

	newenemy = NPC_PickEnemyExt( checkAlerts );

	//if we found one, take it as the enemy
	if( NPC_ValidEnemy( newenemy ) )
	{
		G_SetEnemy( NPC, newenemy );
		return qtrue;
	}

	//[CoOp] SP Code.  Remove enemy since they're not valid at this point.
	G_ClearEnemy( NPC );
	//[/CoOp]
	return qfalse;
}