Пример #1
0
void NPC_BSHuntAndKill( void )
{
	qboolean	turned = qfalse;
	vec3_t		vec;
	float		enemyDist;
	visibility_t	oEVis;
	int			curAnim;

	NPC_CheckEnemy( /*NPCInfo->tempBehavior != BS_HUNT_AND_KILL*/qtrue, qfalse, qtrue );//don't find new enemy if this is tempbehav

	if ( NPC->enemy )
	{
		oEVis = enemyVisibility = NPC_CheckVisibility ( NPC->enemy, CHECK_FOV|CHECK_SHOOT );//CHECK_360|//CHECK_PVS|
		if(enemyVisibility > VIS_PVS)
		{
			if ( !NPC_EnemyTooFar( NPC->enemy, 0, qtrue ) )
			{//Enemy is close enough to shoot - FIXME: this next func does this also, but need to know here for info on whether ot not to turn later
				NPC_CheckCanAttack( 1.0, qfalse );
				turned = qtrue;
			}
		}

		curAnim = NPC->client->ps.legsAnim;
		if(curAnim != BOTH_ATTACK1 && curAnim != BOTH_ATTACK2 && curAnim != BOTH_ATTACK3 && curAnim != BOTH_MELEE1 && curAnim != BOTH_MELEE2 )
		{//Don't move toward enemy if we're in a full-body attack anim
			//FIXME, use IdealDistance to determin if we need to close distance
			VectorSubtract(NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, vec);
			enemyDist = VectorLength(vec);
			if( enemyDist > 48 && ((enemyDist*1.5)*(enemyDist*1.5) >= NPC_MaxDistSquaredForWeapon() ||
				oEVis != VIS_SHOOT ||
				//!(ucmd.buttons & BUTTON_ATTACK) || 
				enemyDist > IdealDistance(NPC)*3 ) )
			{//We should close in?
				NPCInfo->goalEntity = NPC->enemy;

				NPC_MoveToGoal( qtrue );
			}
			else if(enemyDist < IdealDistance(NPC))
			{//We should back off?
				//if(ucmd.buttons & BUTTON_ATTACK)
				{
					NPCInfo->goalEntity = NPC->enemy;
					NPCInfo->goalRadius = 12;
					NPC_MoveToGoal( qtrue );

					ucmd.forwardmove *= -1;
					ucmd.rightmove *= -1;
					VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );

					ucmd.buttons |= BUTTON_WALKING;
				}
			}//otherwise, stay where we are
		}
	}
	else 
	{//ok, stand guard until we find an enemy
		if( NPCInfo->tempBehavior == BS_HUNT_AND_KILL )
		{
			NPCInfo->tempBehavior = BS_DEFAULT;
		}
		else
		{
			NPCInfo->tempBehavior = BS_STAND_GUARD;
			NPC_BSStandGuard();
		}
		return;
	}

	if(!turned)
	{
		NPC_UpdateAngles(qtrue, qtrue);
	}
}
Пример #2
0
void NPC_BSFollowLeader (void)
{
	vec3_t		vec;
	float		leaderDist;
	visibility_t	leaderVis;
	int			curAnim;

	if ( !NPC->client->leader )
	{//ok, stand guard until we find an enemy
		if( NPCInfo->tempBehavior == BS_HUNT_AND_KILL )
		{
			NPCInfo->tempBehavior = BS_DEFAULT;
		}
		else
		{
			NPCInfo->tempBehavior = BS_STAND_GUARD;
			NPC_BSStandGuard();
		}
		return;
	}

	if ( !NPC->enemy  )
	{//no enemy, find one
		NPC_CheckEnemy( NPCInfo->confusionTime<level.time, qfalse );//don't find new enemy if this is tempbehav
		if ( NPC->enemy )
		{//just found one
			NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
		}
		else
		{
			if ( !(NPCInfo->scriptFlags&SCF_IGNORE_ALERTS) )
			{
				int eventID = NPC_CheckAlertEvents( qtrue, qtrue );
				if ( level.alertEvents[eventID].level >= AEL_SUSPICIOUS && (NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES) )
				{
					NPCInfo->lastAlertID = level.alertEvents[eventID].ID;
					if ( !level.alertEvents[eventID].owner || 
						!level.alertEvents[eventID].owner->client || 
						level.alertEvents[eventID].owner->health <= 0 ||
						level.alertEvents[eventID].owner->client->playerTeam != NPC->client->enemyTeam )
					{//not an enemy
					}
					else
					{
						//FIXME: what if can't actually see enemy, don't know where he is... should we make them just become very alert and start looking for him?  Or just let combat AI handle this... (act as if you lost him)
						G_SetEnemy( NPC, level.alertEvents[eventID].owner );
						NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
						NPCInfo->enemyLastSeenTime = level.time;
						TIMER_Set( NPC, "attackDelay", Q_irand( 500, 1000 ) );
					}
				}

			}
		}
		if ( !NPC->enemy )
		{
			if ( NPC->client->leader 
				&& NPC->client->leader->enemy 
				&& NPC->client->leader->enemy != NPC
				&& ( (NPC->client->leader->enemy->client&&NPC->client->leader->enemy->client->playerTeam==NPC->client->enemyTeam)
					||(NPC->client->leader->enemy->svFlags&SVF_NONNPC_ENEMY&&NPC->client->leader->enemy->noDamageTeam==NPC->client->enemyTeam) )
				&& NPC->client->leader->enemy->health > 0 )
			{
				G_SetEnemy( NPC, NPC->client->leader->enemy );
				NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
				NPCInfo->enemyLastSeenTime = level.time;
			}
		}
	}
	else 
	{
		if ( NPC->enemy->health <= 0 || (NPC->enemy->flags&FL_NOTARGET) )
		{
			G_ClearEnemy( NPC );
			if ( NPCInfo->enemyCheckDebounceTime > level.time + 1000 )
			{
				NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 1000, 2000 );
			}
		}
		else if ( NPC->client->ps.weapon && NPCInfo->enemyCheckDebounceTime < level.time )
		{
			NPC_CheckEnemy( (NPCInfo->confusionTime<level.time||NPCInfo->tempBehavior!=BS_FOLLOW_LEADER), qfalse );//don't find new enemy if this is tempbehav
		}
	}
	
	if ( NPC->enemy && NPC->client->ps.weapon )
	{//If have an enemy, face him and fire
		if ( NPC->client->ps.weapon == WP_SABER )//|| NPCInfo->confusionTime>level.time )
		{//lightsaber user or charmed enemy
			if ( NPCInfo->tempBehavior != BS_FOLLOW_LEADER )
			{//not already in a temp bState
				//go after the guy
				NPCInfo->tempBehavior = BS_HUNT_AND_KILL;
				NPC_UpdateAngles(qtrue, qtrue);
				return;
			}
		}

		enemyVisibility = NPC_CheckVisibility ( NPC->enemy, CHECK_FOV|CHECK_SHOOT );//CHECK_360|CHECK_PVS|
		if ( enemyVisibility > VIS_PVS )
		{//face
			vec3_t	enemy_org, muzzle, delta, angleToEnemy;
			float	distanceToEnemy;

			CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org );
			NPC_AimWiggle( enemy_org );

			CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
			
			VectorSubtract( enemy_org, muzzle, delta);
			vectoangles( delta, angleToEnemy );
			distanceToEnemy = VectorNormalize( delta );

			NPCInfo->desiredYaw = angleToEnemy[YAW];
			NPCInfo->desiredPitch = angleToEnemy[PITCH];
			NPC_UpdateFiringAngles( qtrue, qtrue );

			if ( enemyVisibility >= VIS_SHOOT )
			{//shoot
				NPC_AimAdjust( 2 );
				if ( NPC_GetHFOVPercentage( NPC->enemy->currentOrigin, NPC->currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.hfov ) > 0.6f 
					&& NPC_GetHFOVPercentage( NPC->enemy->currentOrigin, NPC->currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.vfov ) > 0.5f )
				{//actually withing our front cone
					WeaponThink( qtrue );
				}
			}
			else
			{
				NPC_AimAdjust( 1 );
			}
			
			//NPC_CheckCanAttack(1.0, qfalse);
		}
		else
		{
			NPC_AimAdjust( -1 );
		}
	}
	else
	{//FIXME: combine with vector calc below
		vec3_t	head, leaderHead, delta, angleToLeader;

		CalcEntitySpot( NPC->client->leader, SPOT_HEAD, leaderHead );
		CalcEntitySpot( NPC, SPOT_HEAD, head );
		VectorSubtract (leaderHead, head, delta);
		vectoangles ( delta, angleToLeader );
		VectorNormalize(delta);
		NPC->NPC->desiredYaw = angleToLeader[YAW];
		NPC->NPC->desiredPitch = angleToLeader[PITCH];
		
		NPC_UpdateAngles(qtrue, qtrue);
	}

	//leader visible?
	leaderVis = NPC_CheckVisibility( NPC->client->leader, CHECK_PVS|CHECK_360|CHECK_SHOOT );//			ent->e_UseFunc = useF_NULL;


	//Follow leader, stay within visibility and a certain distance, maintain a distance from.
	curAnim = NPC->client->ps.legsAnim;
	if ( curAnim != BOTH_ATTACK1 && curAnim != BOTH_ATTACK2 && curAnim != BOTH_ATTACK3 && curAnim != BOTH_MELEE1 && curAnim != BOTH_MELEE2 )
	{//Don't move toward leader if we're in a full-body attack anim
		//FIXME, use IdealDistance to determine if we need to close distance
		float	followDist = 96.0f;//FIXME:  If there are enmies, make this larger?
		float	backupdist, walkdist, minrundist;

		if ( NPCInfo->followDist )
		{
			followDist = NPCInfo->followDist;
		}
		backupdist = followDist/2.0f;
		walkdist = followDist*0.83;
		minrundist = followDist*1.33;

		VectorSubtract(NPC->client->leader->currentOrigin, NPC->currentOrigin, vec);
		leaderDist = VectorLength( vec );//FIXME: make this just nav distance?
		//never get within their radius horizontally
		vec[2] = 0;
		float leaderHDist = VectorLength( vec );
		if( leaderHDist > backupdist && (leaderVis != VIS_SHOOT || leaderDist > walkdist) )
		{//We should close in?
			NPCInfo->goalEntity = NPC->client->leader;

			NPC_SlideMoveToGoal();
			if ( leaderVis == VIS_SHOOT && leaderDist < minrundist )
			{
				ucmd.buttons |= BUTTON_WALKING;
			}
		}
		else if ( leaderDist < backupdist )
		{//We should back off?
			NPCInfo->goalEntity = NPC->client->leader;
			NPC_SlideMoveToGoal();

			//reversing direction
			ucmd.forwardmove = -ucmd.forwardmove;
			ucmd.rightmove   = -ucmd.rightmove;
			VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );
		}//otherwise, stay where we are
		//check for do not enter and stop if there's one there...
		if ( ucmd.forwardmove || ucmd.rightmove || VectorCompare( vec3_origin, NPC->client->ps.moveDir ) )
		{
			NPC_MoveDirClear( ucmd.forwardmove, ucmd.rightmove, qtrue );
		}
	}
}
Пример #3
0
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;
	}
}