//-----------------------------------------------------------------------------
// Purpose: Charge up, prepare to fire and give player time to dodge
//-----------------------------------------------------------------------------
void CNPC_RocketTurret::LockingThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink() )
		return;

	//Turn to face
	UpdateFacing();
	SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );

    if ( m_flTimeLocking == 0.0f )
	{
		// Play lockon sound
		EmitSound ( ROCKET_TURRET_SOUND_LOCKING );
		EmitSound ( ROCKET_TURRET_SOUND_LOCKING, gpGlobals->curtime + ROCKET_TURRET_QUARTER_LOCKON_TIME );
		EmitSound ( ROCKET_TURRET_SOUND_LOCKED, gpGlobals->curtime + ROCKET_TURRET_HALF_LOCKON_TIME );

		ResetSequence(LookupSequence("load"));

		// Change lockon sprite
		UpdateSkin( ROCKET_SKIN_LOCKING );
	}

	m_flTimeLocking += ROCKET_TURRET_THINK_RATE;

	if ( m_flTimeLocking > ROCKET_TURRET_LOCKON_TIME )
	{
		// Set Locked sprite to 'rocket out' color
		UpdateSkin( ROCKET_SKIN_LOCKED );

		FireRocket();
		SetThink ( &CNPC_RocketTurret::FiringThink );
		m_flTimeLocking = 0.0f;
	}
}
예제 #2
0
//-----------------------------------------------------------------------------
// Purpose: Target doesn't exist or has eluded us, so search for one
//-----------------------------------------------------------------------------
void CNPC_CombineCamera::SearchThink()
{
	// Allow descended classes a chance to do something before the think function
	if (PreThink(CAMERA_SEARCHING))
		return;

	SetNextThink( gpGlobals->curtime + 0.05f );

	SetIdealActivity((Activity) ACT_COMBINE_CAMERA_OPEN_IDLE);

	if ( !GetTarget() )
	{
		// Try to acquire a new target
		if (MaintainEnemy())
		{
			SetThink( &CNPC_CombineCamera::ActiveThink );
			return;
		}
	}

	// Display that we're scanning
	m_vecGoalAngles.x = 15.0f;
	m_vecGoalAngles.y = GetAbsAngles().y + (sin(gpGlobals->curtime * 2.0f) * 45.0f);

	// Turn and ping
	UpdateFacing();
	Ping();

	SetEyeState(CAMERA_EYE_IDLE);
}
예제 #3
0
//-----------------------------------------------------------------------------
// Purpose: Retract and stop attacking
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::Retire( void )
{
	if ( PreThink( TURRET_RETIRING ) )
		return;

	//Level out the turret
	m_vecGoalAngles = GetAbsAngles();
	SetNextThink( gpGlobals->curtime );

	//Set ourselves to close
	if ( GetActivity() != ACT_CEILING_TURRET_CLOSE )
	{
		//Set our visible state to dormant
		SetEyeState( TURRET_EYE_DORMANT );

		SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE );
		
		//If we're done moving to our desired facing, close up
		if ( UpdateFacing() == false )
		{
			SetActivity( (Activity) ACT_CEILING_TURRET_CLOSE );
			EmitSound( "NPC_CeilingTurret.Retire" );

			//Notify of the retraction
			m_OnRetire.FireOutput( NULL, this );
		}
	}
	else if ( IsActivityFinished() )
	{	
		SetHeight( CEILING_TURRET_RETRACT_HEIGHT );

		m_bActive		= false;
		m_flLastSight	= 0;

		SetActivity( (Activity) ACT_CEILING_TURRET_CLOSED_IDLE );

		//Go back to auto searching
		if ( m_bAutoStart )
		{
			SetThink( &CNPC_CeilingTurret::AutoSearchThink );
			SetNextThink( gpGlobals->curtime + 0.05f );
		}
		else
		{
			//Set our visible state to dormant
			SetEyeState( TURRET_EYE_DISABLED );
			SetThink( &CNPC_CeilingTurret::SUB_DoNothing );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_RocketTurret::SearchThink()
{
	if ( PreThink() || GetEnemy() == NULL )
		return;

	SetSequence ( LookupSequence( "idle" ) );
	UpdateAimPoint();

	//Update our think time
	SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );

	// Still can't see enemy, zip around frantically
	if ( !m_bHasSightOfEnemy )
	{
		if ( m_flTimeSpentPaused >= m_flPauseLength )
		{
			float flOffsetX = RandomFloat( -5.0f, 5.0f );
			float flOffsetY = RandomFloat( -5.0f, 5.0f );

			if ( fabs(m_flTotalDivergenceX) <= MAX_DIVERGENCE_X || 
				 SignDiffers( m_flTotalDivergenceX, flOffsetX ) )
			{
				m_flTotalDivergenceX += flOffsetX;
				m_vecGoalAngles.x += flOffsetX;
			}

			if ( fabs(m_flTotalDivergenceY) <= MAX_DIVERGENCE_Y ||
				 SignDiffers( m_flTotalDivergenceY, flOffsetY ) )
			{
				m_flTotalDivergenceY += flOffsetY;
				m_vecGoalAngles.y += flOffsetY;
			}

			// Reset pause timer
			m_flTimeSpentPaused = 0.0f;
			m_flPauseLength = RandomFloat( 0.3f, 2.5f );
		}
		m_flTimeSpentPaused += ROCKET_TURRET_THINK_RATE;
	}
	else
	{
		// Found target, go back to following it
		SetThink( &CNPC_RocketTurret::FollowThink );
		SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );
	}

	// Move beam towards goal angles
	UpdateFacing();
}
//-----------------------------------------------------------------------------
// Purpose: The turret has been tipped over and will thrash for awhile
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::HeldThink( void )
{
	PreThink( (turretState_e)PORTAL_TURRET_PICKUP );

	SetNextThink( gpGlobals->curtime + 0.05f );
	SetEnemy( NULL );

	StudioFrameAdvance();

	IPhysicsObject *pTurretPhys = VPhysicsGetObject();

	// If we're not held anymore, stop thrashing
	if ( !(pTurretPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) )
	{
		m_fNextTalk = gpGlobals->curtime + 1.25f;

		if ( m_lifeState == LIFE_ALIVE )
			SetThink( &CNPC_FloorTurret::ActiveThink );
		else
			SetThink( &CNPC_FloorTurret::InactiveThink );
	}

	LaserOn();
	RopesOn();

	//See if we should continue to thrash
	if ( !IsDissolving() )
	{
		if ( m_flShotTime < gpGlobals->curtime )
		{
			SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );

			DryFire();

			m_flShotTime = gpGlobals->curtime + RandomFloat( 0.25f, 0.75f );

			m_vecGoalAngles.x = GetAbsAngles().x + RandomFloat( -15, 15 );
			m_vecGoalAngles.y = GetAbsAngles().y + RandomFloat( -40, 40 );
		}

		UpdateFacing();
	}
}
예제 #6
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pTarget - 
//-----------------------------------------------------------------------------
void CNPC_CombineCamera::TrackTarget( CBaseEntity *pTarget )
{
	if (!pTarget)
		return;

	// Calculate direction to target
	Vector vecMid = EyePosition();
	Vector vecMidTarget = pTarget->BodyTarget(vecMid);
	Vector vecDirToTarget = vecMidTarget - vecMid;	

	// We want to look at the target's eyes so we don't jitter
	Vector vecDirToTargetEyes = pTarget->WorldSpaceCenter() - vecMid;
	VectorNormalize(vecDirToTargetEyes);

	QAngle vecAnglesToTarget;
	VectorAngles(vecDirToTargetEyes, vecAnglesToTarget);

	// Draw debug info
	if (g_debug_combine_camera.GetBool())
	{
		NDebugOverlay::Cross3D(vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05);
		NDebugOverlay::Cross3D(pTarget->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05);
		NDebugOverlay::Line(vecMid, pTarget->WorldSpaceCenter(), 0, 255, 0, false, 0.05);

		NDebugOverlay::Cross3D(vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05);
		NDebugOverlay::Cross3D(vecMidTarget, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05);
		NDebugOverlay::Line(vecMid, vecMidTarget, 0, 255, 0, false, 0.05f);
	}

	Vector vecMuzzle, vecMuzzleDir;
	QAngle vecMuzzleAng;
	
	GetAttachment("eyes", vecMuzzle, &vecMuzzleDir);
	
	SetIdealActivity((Activity) ACT_COMBINE_CAMERA_OPEN_IDLE);

	m_vecGoalAngles.y = vecAnglesToTarget.y;
	m_vecGoalAngles.x = vecAnglesToTarget.x;

	// Turn to face
	UpdateFacing();
}
예제 #7
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_CombineCamera::DeathThink()
{
	if (PreThink(CAMERA_DEAD))
		return;

	// Level out our angles
	m_vecGoalAngles = GetAbsAngles();
	SetNextThink( gpGlobals->curtime + 0.1f );

	if (m_lifeState != LIFE_DEAD)
	{
		m_lifeState = LIFE_DEAD;

		EmitSound("NPC_CombineCamera.Die");

		// lots of smoke
		Vector pos;
		CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos );
		
		CBroadcastRecipientFilter filter;
		
		te->Smoke(filter, 0.0, &pos, g_sModelIndexSmoke, 2.5, 10);
		
		g_pEffects->Sparks(pos);

		SetActivity((Activity) ACT_COMBINE_CAMERA_CLOSE);
	}

	StudioFrameAdvance();

	if (IsActivityFinished() && (UpdateFacing() == false))
	{
		SetHeight(COMBINE_CAMERA_RETRACT_HEIGHT);

		m_flPlaybackRate = 0;
		SetThink(NULL);
	}
}
//-----------------------------------------------------------------------------
// Purpose: Avoid aiming/drawing beams while opening and closing
// Input  :  - 
//-----------------------------------------------------------------------------
void CNPC_RocketTurret::ClosingThink()
{
	LaserOff();

	// Require these poses for this animation
	QAngle vecNeutralAngles ( 0, 90, 0 );
	m_vecGoalAngles = vecNeutralAngles;

	// Once we're within 10 degrees of the neutral pose, start close animation.
	if ( UpdateFacing() <= 10.0f )
	{
		StudioFrameAdvance();
	}

	SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );

	// Start following player after we're fully opened
	float flCurProgress = GetCycle();
	if ( flCurProgress >= 0.99f )
	{
		SetThink( NULL );
		SetNextThink( TICK_NEVER_THINK );
	}
}
예제 #9
0
void GamepadController::Update() {
  UpdateFacing();
  UpdateButtons();
}
예제 #10
0
//-----------------------------------------------------------------------------
// Purpose: Target doesn't exist or has eluded us, so search for one
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::SearchThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_SEARCHING ) )
		return;

	SetNextThink( gpGlobals->curtime + 0.05f );

	SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );

	//If our enemy has died, pick a new enemy
	if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) )
	{
		SetEnemy( NULL );
	}

	//Acquire the target
	if ( GetEnemy() == NULL )
	{
		HackFindEnemy();
	}

	LaserOn();

	CBaseEntity *pEnemy = GetEnemy();

	//If we've found a target, spin up the barrel and start to attack
	if ( pEnemy != NULL )
	{
		//Get our shot positions
		Vector vecMid = EyePosition();
		Vector vecMidEnemy = pEnemy->BodyTarget( vecMid );

		//Look for our current enemy
		bool bEnemyInFOV = FInViewCone( pEnemy );
		bool bEnemyVisible = FVisible( pEnemy );

		//Calculate dir and dist to enemy
		Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
		m_flDistToEnemy = VectorNormalize( vecDirToEnemy );

		// If the enemy isn't in the normal fov, check the fov through portals
		CProp_Portal *pPortal = NULL;
		pPortal = FInViewConeThroughPortal( pEnemy );

		if ( pPortal && FVisibleThroughPortal( pPortal, pEnemy ) )
		{
			// Translate our target across the portal
			Vector vecMidEnemyTransformed;
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecMidEnemy, vecMidEnemyTransformed );

			//Calculate dir and dist to enemy
			Vector	vecDirToEnemyTransformed = vecMidEnemyTransformed - vecMid;	
			float	flDistToEnemyTransformed = VectorNormalize( vecDirToEnemyTransformed );

			// If it's not visible through normal means or the enemy is closer through the portal, use the translated info
			if ( !bEnemyInFOV || !bEnemyVisible || flDistToEnemyTransformed < m_flDistToEnemy )
			{
				bEnemyInFOV = true;
				bEnemyVisible = true;
				vecMidEnemy = vecMidEnemyTransformed;
				vecDirToEnemy = vecDirToEnemyTransformed;
				m_flDistToEnemy = flDistToEnemyTransformed;
			}
		}

		// Give enemies that are farther away a longer grace period
		float fDistanceRatio = m_flDistToEnemy / PORTAL_FLOOR_TURRET_RANGE;
		m_flShotTime = gpGlobals->curtime + fDistanceRatio * fDistanceRatio * PORTAL_FLOOR_TURRET_MAX_SHOT_DELAY;

		m_flLastSight = 0;
		SetThink( &CNPC_FloorTurret::ActiveThink );
		SetEyeState( TURRET_EYE_SEE_TARGET );

		SpinUp();

		if ( gpGlobals->curtime > m_flNextActivateSoundTime )
		{
			EmitSound( "NPC_FloorTurret.Activate" );
			m_flNextActivateSoundTime = gpGlobals->curtime + 3.0;
		}
		return;
	}

	//Are we out of time and need to retract?
	if ( gpGlobals->curtime > m_flLastSight )
	{
		//Before we retrace, make sure that we are spun down.
		m_flLastSight = 0;
		SetThink( &CNPC_FloorTurret::Retire );
		return;
	}

	//Display that we're scanning
	m_vecGoalAngles.x = GetAbsAngles().x + ( sin( ( m_flLastSight + gpGlobals->curtime * m_fSearchSpeed ) * 1.5f ) * 20.0f );
	m_vecGoalAngles.y = GetAbsAngles().y + ( sin( ( m_flLastSight + gpGlobals->curtime * m_fSearchSpeed ) * 2.5f ) * 20.0f );

	//Turn and ping
	UpdateFacing();
	Ping();

	// Update rope positions
	for ( int iRope = 0; iRope < PORTAL_FLOOR_TURRET_NUM_ROPES; ++iRope )
	{
		if ( m_hRopes[ iRope ] )
		{
			m_hRopes[ iRope ]->EndpointsChanged();
		}
	}
}
예제 #11
0
void CNPC_Portal_FloorTurret::ActiveThink( void )
{
	LaserOn();

	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_ACTIVE ) )
		return;

	HackFindEnemy();

	//Update our think time
	SetNextThink( gpGlobals->curtime + 0.1f );

	CBaseEntity *pEnemy = GetEnemy();

	//If we've become inactive, go back to searching
	if ( ( m_bActive == false ) || ( pEnemy == NULL ) )
	{
		SetEnemy( NULL );
		m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT;
		SetThink( &CNPC_FloorTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();
		return;
	}

	//Get our shot positions
	Vector vecMid = EyePosition();
	Vector vecMidEnemy = pEnemy->BodyTarget( vecMid );

	// Store off our last seen location so we can suppress it later
	m_vecEnemyLKP = vecMidEnemy;

	//Look for our current enemy
	bool bEnemyInFOV = FInViewCone( pEnemy );
	bool bEnemyVisible = FVisible( pEnemy ) && pEnemy->IsAlive();

	//Calculate dir and dist to enemy
	Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
	m_flDistToEnemy = VectorNormalize( vecDirToEnemy );

	// If the enemy isn't in the normal fov, check the fov through portals
	CProp_Portal *pPortal = NULL;
	if ( pEnemy->IsAlive() )
	{
		pPortal = FInViewConeThroughPortal( pEnemy );

		if ( pPortal && FVisibleThroughPortal( pPortal, pEnemy ) )
		{
			// Translate our target across the portal
			Vector vecMidEnemyTransformed;
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecMidEnemy, vecMidEnemyTransformed );

			//Calculate dir and dist to enemy
			Vector	vecDirToEnemyTransformed = vecMidEnemyTransformed - vecMid;	
			float	flDistToEnemyTransformed = VectorNormalize( vecDirToEnemyTransformed );

			// If it's not visible through normal means or the enemy is closer through the portal, use the translated info
			if ( !bEnemyInFOV || !bEnemyVisible || flDistToEnemyTransformed < m_flDistToEnemy )
			{
				bEnemyInFOV = true;
				bEnemyVisible = true;
				vecMidEnemy = vecMidEnemyTransformed;
				vecDirToEnemy = vecDirToEnemyTransformed;
				m_flDistToEnemy = flDistToEnemyTransformed;
			}
			else
			{
				pPortal = NULL;
			}
		}
		else
		{
			pPortal = NULL;
		}
	}

	//Draw debug info
	if ( g_debug_turret.GetBool() )
	{
		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 );

		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f );
	}

	//See if they're past our FOV of attack
	if ( bEnemyInFOV == false )
	{
		// Should we look for a new target?
		ClearEnemyMemory();
		SetEnemy( NULL );

		if ( m_spawnflags & SF_FLOOR_TURRET_FASTRETIRE )
		{
			// Retire quickly in this case. (The case where we saw the player, but he hid again).
			m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_SHORT_WAIT;
		}
		else
		{
			m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT;
		}

		SetThink( &CNPC_FloorTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();

		SpinDown();

		return;
	}

	//Current enemy is not visible
	if ( ( bEnemyVisible == false ) || ( m_flDistToEnemy > PORTAL_FLOOR_TURRET_RANGE ))
	{
		m_flLastSight = gpGlobals->curtime + 2.0f;

		ClearEnemyMemory();
		SetEnemy( NULL );
		SetThink( &CNPC_FloorTurret::SuppressThink );

		return;
	}

	if ( g_debug_turret.GetBool() )
	{
		Vector vecMuzzle, vecMuzzleDir;

		UpdateMuzzleMatrix();
		MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir );
		MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle );

		// Visualize vertical firing ranges
		for ( int i = 0; i < 4; i++ )
		{
			QAngle angMaxDownPitch = GetAbsAngles();

			switch( i )
			{
			case 0:	angMaxDownPitch.x -= 15; break;
			case 1:	angMaxDownPitch.x += 15; break;
			case 2:	angMaxDownPitch.x -= 25; break;
			case 3:	angMaxDownPitch.x += 25; break;
			default:
				break;
			}

			Vector vecMaxDownPitch;
			AngleVectors( angMaxDownPitch, &vecMaxDownPitch );
			NDebugOverlay::Line( vecMuzzle, vecMuzzle + (vecMaxDownPitch*256), 255, 255, 255, false, 0.1 );
		}
	}

	if ( m_flShotTime < gpGlobals->curtime )
	{
		Vector vecMuzzle, vecMuzzleDir;

		UpdateMuzzleMatrix();
		MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir );
		MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle );

		Vector2D vecDirToEnemy2D = vecDirToEnemy.AsVector2D();
		Vector2D vecMuzzleDir2D = vecMuzzleDir.AsVector2D();

		bool bCanShoot = true;
		float minCos3d = DOT_10DEGREE; // 10 degrees slop

		if ( m_flDistToEnemy < 60.0 )
		{
			vecDirToEnemy2D.NormalizeInPlace();
			vecMuzzleDir2D.NormalizeInPlace();

			bCanShoot = ( vecDirToEnemy2D.Dot(vecMuzzleDir2D) >= DOT_10DEGREE );
			minCos3d = 0.7071; // 45 degrees
		}

		//Fire the gun
		if ( bCanShoot ) // 10 degree slop XY
		{
			float dot3d = DotProduct( vecDirToEnemy, vecMuzzleDir );

			if( m_bOutOfAmmo )
			{
				DryFire();
			}
			else
			{
				if ( dot3d >= minCos3d ) 
				{
					SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
					SetActivity( (Activity)( ( m_bShootWithBottomBarrels ) ? ( ACT_FLOOR_TURRET_FIRE2 ) : ( ACT_FLOOR_TURRET_FIRE ) ) );

					//Fire the weapon
#if !DISABLE_SHOT
					Shoot( vecMuzzle, vecMuzzleDir, (dot3d < DOT_10DEGREE) );
#endif
				}
			}
		} 
	}
	else
	{
		SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
	}

	//If we can see our enemy, face it
	if ( bEnemyVisible )
	{
		//We want to look at the enemy's eyes so we don't jitter
		Vector vEnemyWorldSpaceCenter = pEnemy->WorldSpaceCenter();
		if ( pPortal && pPortal->IsActivedAndLinked() )
		{
			// Translate our target across the portal
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vEnemyWorldSpaceCenter, vEnemyWorldSpaceCenter );
		}

		Vector	vecDirToEnemyEyes = vEnemyWorldSpaceCenter - vecMid;
		VectorNormalize( vecDirToEnemyEyes );

		QAngle vecAnglesToEnemy;
		VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy );

		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;
	}

	//Turn to face
	UpdateFacing();
}
예제 #12
0
void CNPC_Portal_FloorTurret::FireBullet( const char *pTargetName )
{
	CBaseEntity *pEnemy = gEntList.FindEntityByName( NULL, pTargetName );
	if ( !pEnemy )
		return;

	//Get our shot positions
	Vector vecMid = EyePosition();
	Vector vecMidEnemy = pEnemy->BodyTarget( vecMid );

	// Store off our last seen location so we can suppress it later
	m_vecEnemyLKP = vecMidEnemy;

	//Calculate dir and dist to enemy
	Vector	vecDirToEnemy = vecMidEnemy - vecMid;
	m_flDistToEnemy = VectorNormalize( vecDirToEnemy );

	//We want to look at the enemy's eyes so we don't jitter
	Vector	vecDirToEnemyEyes = vecMidEnemy - vecMid;
	VectorNormalize( vecDirToEnemyEyes );

	QAngle vecAnglesToEnemy;
	VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy );

	Vector vecMuzzle, vecMuzzleDir;
	GetAttachment( m_iMuzzleAttachment, vecMuzzle, &vecMuzzleDir );

	if ( m_flShotTime < gpGlobals->curtime )
	{
		Vector2D vecDirToEnemy2D = vecDirToEnemy.AsVector2D();
		Vector2D vecMuzzleDir2D = vecMuzzleDir.AsVector2D();

		if ( m_flDistToEnemy < 60.0 )
		{
			vecDirToEnemy2D.NormalizeInPlace();
			vecMuzzleDir2D.NormalizeInPlace();
		}

		//Fire the gun
		if( m_bOutOfAmmo )
		{
			DryFire();
		}
		else
		{
			SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
			SetActivity( (Activity)( ( m_bShootWithBottomBarrels ) ? ( ACT_FLOOR_TURRET_FIRE2 ) : ( ACT_FLOOR_TURRET_FIRE ) ) );

			//Fire the weapon
#if !DISABLE_SHOT
			Shoot( vecMuzzle, vecDirToEnemy, true );
#endif
		}

		//If we can see our enemy, face it
		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;

		//Turn to face
		UpdateFacing();

		EmitSound( "NPC_FloorTurret.Alert" );
		SetThink( &CNPC_FloorTurret::SuppressThink );
	}
}
예제 #13
0
//-----------------------------------------------------------------------------
// Purpose: The turret has been tipped over and will thrash for awhile
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::TippedThink( void )
{
	PreThink( TURRET_TIPPED );

	SetNextThink( gpGlobals->curtime + 0.05f );
	SetEnemy( NULL );

	StudioFrameAdvance();
	// If we're not on side anymore, stop thrashing
	if ( !OnSide() && VPhysicsGetObject()->GetContactPoint( NULL, NULL ) )
	{
		ReturnToLife();
		return;
	}

	LaserOn();
	RopesOn();

	//See if we should continue to thrash
	if ( gpGlobals->curtime < m_flThrashTime && !IsDissolving() )
	{
		if ( m_flShotTime < gpGlobals->curtime )
		{
			if( m_bOutOfAmmo )
			{
				SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
				DryFire();
			}
			else
			{
				Vector vecMuzzle, vecMuzzleDir;
				GetAttachment( m_iMuzzleAttachment, vecMuzzle, &vecMuzzleDir );

				SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
				SetActivity( (Activity)( ( m_bShootWithBottomBarrels ) ? ( ACT_FLOOR_TURRET_FIRE2 ) : ( ACT_FLOOR_TURRET_FIRE ) ) );

#if !DISABLE_SHOT
				Shoot( vecMuzzle, vecMuzzleDir );
#endif
			}

			m_flShotTime = gpGlobals->curtime + 0.05f;
		}

		m_vecGoalAngles.x = GetAbsAngles().x + random->RandomFloat( -60, 60 );
		m_vecGoalAngles.y = GetAbsAngles().y + random->RandomFloat( -60, 60 );

		UpdateFacing();
	}
	else
	{
		//Face forward
		m_vecGoalAngles = GetAbsAngles();

		//Set ourselves to close
		if ( GetActivity() != ACT_FLOOR_TURRET_CLOSE )
		{
			SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );

			//If we're done moving to our desired facing, close up
			if ( UpdateFacing() == false )
			{
				//Make any last death noises and anims
				EmitSound( "NPC_FloorTurret.Die" );
				EmitSound( GetTurretTalkName( PORTAL_TURRET_DISABLED ) );
				SpinDown();

				SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSE );
				EmitSound( "NPC_FloorTurret.Retract" );

				CTakeDamageInfo	info;
				info.SetDamage( 1 );
				info.SetDamageType( DMG_CRUSH );
				Event_Killed( info );
			}
		}
		else if ( IsActivityFinished() )
		{	
			m_bActive		= false;
			m_flLastSight	= 0;

			SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSED_IDLE );

			// Don't need to store last NPC anymore, because I've been knocked over
			if ( m_hLastNPCToKickMe )
			{
				m_hLastNPCToKickMe = NULL;
				m_flKnockOverFailedTime = 0;
			}

			//Try to look straight
			if ( UpdateFacing() == false )
			{
				m_OnTipped.FireOutput( this, this );
				SetEyeState( TURRET_EYE_DEAD );
				//SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER );

				// Start thinking slowly to see if we're ever set upright somehow
				SetThink( &CNPC_FloorTurret::InactiveThink );
				SetNextThink( gpGlobals->curtime + 1.0f );
				RopesOff();
			}
		}
	}
}
예제 #14
0
//-----------------------------------------------------------------------------
// Purpose: Target doesn't exist or has eluded us, so search for one
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::SearchThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_SEARCHING ) )
		return;

	SetNextThink( gpGlobals->curtime + 0.05f );

	SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE );

	//If our enemy has died, pick a new enemy
	if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) )
	{
		SetEnemy( NULL );
	}

	//Acquire the target
 	if ( GetEnemy() == NULL )
	{
		GetSenses()->Look( CEILING_TURRET_RANGE );
		CBaseEntity *pEnemy = BestEnemy();
		if ( pEnemy )
		{
			SetEnemy( pEnemy );
		}
	}

	//If we've found a target, spin up the barrel and start to attack
	if ( GetEnemy() != NULL )
	{
		//Give players a grace period
		if ( GetEnemy()->IsPlayer() )
		{
			m_flShotTime  = gpGlobals->curtime + 0.5f;
		}
		else
		{
			m_flShotTime  = gpGlobals->curtime + 0.1f;
		}

		m_flLastSight = 0;
		SetThink( &CNPC_CeilingTurret::ActiveThink );
		SetEyeState( TURRET_EYE_SEE_TARGET );

		SpinUp();
		EmitSound( "NPC_CeilingTurret.Active" );
		return;
	}

	//Are we out of time and need to retract?
 	if ( gpGlobals->curtime > m_flLastSight )
	{
		//Before we retrace, make sure that we are spun down.
		m_flLastSight = 0;
		SetThink( &CNPC_CeilingTurret::Retire );
		return;
	}
	
	//Display that we're scanning
	m_vecGoalAngles.x = 15.0f;
	m_vecGoalAngles.y = GetAbsAngles().y + ( sin( gpGlobals->curtime * 2.0f ) * 45.0f );

	//Turn and ping
	UpdateFacing();
	Ping();
}
예제 #15
0
//-----------------------------------------------------------------------------
// Purpose: Allows the turret to fire on targets if they're visible
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::ActiveThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_ACTIVE ) )
		return;

	//Update our think time
	SetNextThink( gpGlobals->curtime + 0.1f );

	//If we've become inactive, go back to searching
	if ( ( m_bActive == false ) || ( GetEnemy() == NULL ) )
	{
		SetEnemy( NULL );
		SetLastSightTime();
		SetThink( &CNPC_CeilingTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();
		return;
	}
	
	//Get our shot positions
	Vector vecMid = EyePosition();
	Vector vecMidEnemy = GetEnemy()->GetAbsOrigin();

	//Store off our last seen location
	UpdateEnemyMemory( GetEnemy(), vecMidEnemy );

	//Look for our current enemy
	bool bEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() ) && GetEnemy()->IsAlive();

	//Calculate dir and dist to enemy
	Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
	float	flDistToEnemy = VectorNormalize( vecDirToEnemy );

	//We want to look at the enemy's eyes so we don't jitter
	Vector	vecDirToEnemyEyes = GetEnemy()->WorldSpaceCenter() - vecMid;
	VectorNormalize( vecDirToEnemyEyes );

	QAngle vecAnglesToEnemy;
	VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy );

	//Draw debug info
	if ( g_debug_turret_ceiling.GetBool() )
	{
		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 );

		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f );
	}

	//Current enemy is not visible
	if ( ( bEnemyVisible == false ) || ( flDistToEnemy > CEILING_TURRET_RANGE ))
	{
		if ( m_flLastSight )
		{
			m_flLastSight = gpGlobals->curtime + 0.5f;
		}
		else if ( gpGlobals->curtime > m_flLastSight )
		{
			// Should we look for a new target?
			ClearEnemyMemory();
			SetEnemy( NULL );
			SetLastSightTime();
			SetThink( &CNPC_CeilingTurret::SearchThink );
			m_vecGoalAngles = GetAbsAngles();
			
			SpinDown();

			return;
		}

		bEnemyVisible = false;
	}

	Vector vecMuzzle, vecMuzzleDir;
	QAngle vecMuzzleAng;
	
	GetAttachment( "eyes", vecMuzzle, vecMuzzleAng );
	AngleVectors( vecMuzzleAng, &vecMuzzleDir );
	
	if ( m_flShotTime < gpGlobals->curtime )
	{
		//Fire the gun
		if ( DotProduct( vecDirToEnemy, vecMuzzleDir ) >= 0.9848 ) // 10 degree slop
		{
			if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO )
			{
				SetActivity( (Activity) ACT_CEILING_TURRET_DRYFIRE );
			}
			else
			{
				SetActivity( (Activity) ACT_CEILING_TURRET_FIRE );
			}
			
			//Fire the weapon
			Shoot( vecMuzzle, vecMuzzleDir );
		} 
	}
	else
	{
		SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE );
	}

	//If we can see our enemy, face it
	if ( bEnemyVisible )
	{
		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;
	}

	//Turn to face
	UpdateFacing();
}
//-----------------------------------------------------------------------------
// Purpose: Allows the turret to fire on targets if they're visible
//-----------------------------------------------------------------------------
void CNPC_RocketTurret::FollowThink( void )
{
	// Default to player as enemy
	if ( GetEnemy() == NULL )
	{
		SetEnemy( UTIL_GetLocalPlayer() );
	}

	SetSequence ( LookupSequence( "idle" ) );
	//Allow descended classes a chance to do something before the think function
	if ( PreThink() || GetEnemy() == NULL )
	{
		return;
	}
	//Update our think time
	SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );

	UpdateAimPoint();

	m_vecGoalAngles = m_vecAnglesToEnemy;

	// Chase enemy
	if ( !m_bHasSightOfEnemy )
	{
		// Aim at the last known location
		m_vecGoalAngles = m_vecCurrentAngles;

		// Lost sight, move to search think
		SetThink( &CNPC_RocketTurret::SearchThink );
	}

	//Turn to face
	UpdateFacing();

	// If our facing direction hits our enemy, fire the beam
	Ray_t rayDmg;
	Vector vForward;
	AngleVectors( m_vecCurrentAngles, &vForward, NULL, NULL );
	Vector vEndPoint = EyePosition() + vForward*ROCKET_TURRET_RANGE;
	rayDmg.Init( EyePosition(), vEndPoint );
	rayDmg.m_IsRay = true;
	trace_t traceDmg;

	// This version reorients through portals
	CTraceFilterSimple subfilter( this, COLLISION_GROUP_NONE );
	CTraceFilterTranslateClones filter ( &subfilter );
	float flRequiredParameter = 2.0f;
	CProp_Portal* pFirstPortal = UTIL_Portal_FirstAlongRay( rayDmg, flRequiredParameter );
	UTIL_Portal_TraceRay_Bullets( pFirstPortal, rayDmg, MASK_VISIBLE_AND_NPCS, &filter, &traceDmg, false );

	if ( traceDmg.m_pEnt )
	{
		// This thing we're hurting is our enemy
		if ( traceDmg.m_pEnt == GetEnemy() )
		{
			// If we're past the cooldown time, fire another rocket
			if ( (gpGlobals->curtime - m_flTimeLastFired) > ROCKET_TURRET_ROCKET_FIRE_COOLDOWN_TIME )
			{
				SetThink( &CNPC_RocketTurret::LockingThink );
			}
		}
	}
}