Exemple #1
0
void NPC_BSGrenadier_Attack( void ) {
	//Don't do anything if we're hurt
	if ( NPC->painDebounceTime > level.time ) {
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	//NPC_CheckEnemy( qtrue, qfalse );
	//If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt( qfalse ) == qfalse )//!NPC->enemy )//
	{
		NPC->enemy = NULL;
		NPC_BSGrenadier_Patrol();//FIXME: or patrol?
		return;
	}

	if ( TIMER_Done( NPC, "flee" ) && NPC_CheckForDanger( NPC_CheckAlertEvents( qtrue, qtrue, -1, qfalse, AEL_DANGER ) ) ) {//going to run
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	if ( !NPC->enemy ) {//WTF?  somehow we lost our enemy?
		NPC_BSGrenadier_Patrol();//FIXME: or patrol?
		return;
	}

	enemyLOS3 = enemyCS3 = qfalse;
	move3 = qtrue;
	faceEnemy3 = qfalse;
	shoot3 = qfalse;
	enemyDist3 = DistanceSquared( &NPC->enemy->r.currentOrigin, &NPC->r.currentOrigin );

	//See if we should switch to melee attack
	if ( enemyDist3 < 16384 //128
		&& (!NPC->enemy->client
		|| NPC->enemy->client->ps.weapon != WP_SABER
		|| BG_SabersOff( &NPC->enemy->client->ps )
		)
		) {//enemy is close and not using saber
		if ( NPC->client->ps.weapon == WP_THERMAL ) {//grenadier
			trace_t	trace;
			trap->Trace( &trace, &NPC->r.currentOrigin, &NPC->enemy->r.mins, &NPC->enemy->r.maxs, &NPC->enemy->r.currentOrigin, NPC->s.number, NPC->enemy->clipmask, qfalse, 0, 0 );
			if ( !trace.allsolid && !trace.startsolid && (FloatCompare( trace.fraction, 1.0f, 0.001f ) || trace.entityNum == NPC->enemy->s.number) ) {//I can get right to him
				//reset fire-timing variables
				NPC_ChangeWeapon( WP_STUN_BATON );
				if ( !(NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )//NPCInfo->behaviorState == BS_STAND_AND_SHOOT )
				{//FIXME: should we be overriding scriptFlags?
					NPCInfo->scriptFlags |= SCF_CHASE_ENEMIES;//NPCInfo->behaviorState = BS_HUNT_AND_KILL;
				}
			}
		}
	}
	else if ( enemyDist3 > 65536 || (NPC->enemy->client && NPC->enemy->client->ps.weapon == WP_SABER && !NPC->enemy->client->ps.saberHolstered) )//256
	{//enemy is far or using saber
		if ( NPC->client->ps.weapon == WP_STUN_BATON && (NPC->client->ps.stats[STAT_WEAPONS] & (1 << WP_THERMAL)) ) {//fisticuffs, make switch to thermal if have it
			//reset fire-timing variables
			NPC_ChangeWeapon( WP_THERMAL );
		}
	}

	//can we see our target?
	if ( NPC_ClearLOS4( NPC->enemy ) ) {
		NPCInfo->enemyLastSeenTime = level.time;
		enemyLOS3 = qtrue;

		if ( NPC->client->ps.weapon == WP_STUN_BATON ) {
			if ( enemyDist3 <= 4096 && InFOV3( &NPC->enemy->r.currentOrigin, &NPC->r.currentOrigin, &NPC->client->ps.viewangles, 90, 45 ) )//within 64 & infront
			{
				VectorCopy( &NPC->enemy->r.currentOrigin, &NPCInfo->enemyLastSeenLocation );
				enemyCS3 = qtrue;
			}
		}
		else if ( InFOV3( &NPC->enemy->r.currentOrigin, &NPC->r.currentOrigin, &NPC->client->ps.viewangles, 45, 90 ) ) {//in front of me
			//can we shoot our target?
			//FIXME: how accurate/necessary is this check?
			int hit = NPC_ShotEntity( NPC->enemy, NULL );
			gentity_t *hitEnt = &g_entities[hit];
			if ( hit == NPC->enemy->s.number
				|| (hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPC->client->enemyTeam) ) {
				float enemyHorzDist;

				VectorCopy( &NPC->enemy->r.currentOrigin, &NPCInfo->enemyLastSeenLocation );
				enemyHorzDist = DistanceHorizontalSquared( &NPC->enemy->r.currentOrigin, &NPC->r.currentOrigin );
				if ( enemyHorzDist < 1048576 ) {//within 1024
					enemyCS3 = qtrue;
					NPC_AimAdjust( 2 );//adjust aim better longer we have clear shot at enemy
				}
				else {
					NPC_AimAdjust( 1 );//adjust aim better longer we can see enemy
				}
			}
		}
	}
	else {
		NPC_AimAdjust( -1 );//adjust aim worse longer we cannot see enemy
	}
	/*
	else if ( trap->InPVS( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) )
	{
	NPCInfo->enemyLastSeenTime = level.time;
	faceEnemy3 = qtrue;
	}
	*/

	if ( enemyLOS3 ) {//FIXME: no need to face enemy if we're moving to some other goal and he's too far away to shoot?
		faceEnemy3 = qtrue;
	}

	if ( enemyCS3 ) {
		shoot3 = qtrue;
		if ( NPC->client->ps.weapon == WP_THERMAL ) {//don't chase and throw
			move3 = qfalse;
		}
		else if ( NPC->client->ps.weapon == WP_STUN_BATON && enemyDist3 < (NPC->r.maxs.x + NPC->enemy->r.maxs.y + 16)*(NPC->r.maxs.x + NPC->enemy->r.maxs.x + 16) ) {//close enough
			move3 = qfalse;
		}
	}//this should make him chase enemy when out of range...?

	//Check for movement to take care of
	Grenadier_CheckMoveState();

	//See if we should override shooting decision with any special considerations
	Grenadier_CheckFireState();

	if ( move3 ) {//move toward goal
		if ( NPCInfo->goalEntity )//&& ( NPCInfo->goalEntity != NPC->enemy || enemyDist3 > 10000 ) )//100 squared
		{
			move3 = Grenadier_Move();
		}
		else {
			move3 = qfalse;
		}
	}

	if ( !move3 ) {
		if ( !TIMER_Done( NPC, "duck" ) ) {
			ucmd.upmove = -127;
		}
		//FIXME: what about leaning?
	}
	else {//stop ducking!
		TIMER_Set( NPC, "duck", -1 );
	}

	if ( !faceEnemy3 ) {//we want to face in the dir we're running
		if ( move3 ) {//don't run away and shoot
			NPCInfo->desiredYaw = NPCInfo->lastPathAngles.yaw;
			NPCInfo->desiredPitch = 0;
			shoot3 = qfalse;
		}
		NPC_UpdateAngles( qtrue, qtrue );
	}
	else// if ( faceEnemy3 )
	{//face the enemy
		NPC_FaceEnemy( qtrue );
	}

	if ( NPCInfo->scriptFlags&SCF_DONT_FIRE ) {
		shoot3 = qfalse;
	}

	//FIXME: don't shoot right away!
	if ( shoot3 ) {//try to shoot if it's time
		if ( TIMER_Done( NPC, "attackDelay" ) ) {
			if ( !(NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here
			{
				WeaponThink( qtrue );
				TIMER_Set( NPC, "attackDelay", NPCInfo->shotTime - level.time );
			}

		}
	}
}
Exemple #2
0
		bool operator==(const Vector4& p_lhs, const Vector4& p_rhs) {
			return FloatCompare(p_lhs.x, p_rhs.x) && FloatCompare(p_lhs.y, p_rhs.y) && FloatCompare(p_lhs.z, p_rhs.z) && FloatCompare(p_lhs.w, p_rhs.w);
		}