⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hl1_npc_osprey.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}
	Vector vecImpulse( 0, 0, 0 );
	// add gravity
	vecImpulse.z -= 38.4; // 32ft/sec
	ApplyAbsVelocityImpulse( vecImpulse );

}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
BEGIN_DATADESC( CBaseHelicopter )

	DEFINE_THINKFUNC( CBaseHelicopter, HelicopterThink ),
	DEFINE_THINKFUNC( CBaseHelicopter, CallDyingThink ),
	DEFINE_ENTITYFUNC( CBaseHelicopter, CrashTouch ),
	DEFINE_ENTITYFUNC( CBaseHelicopter, FlyTouch ),

	DEFINE_FIELD( CBaseHelicopter, m_flForce,			FIELD_FLOAT ),
	DEFINE_FIELD( CBaseHelicopter, m_fHelicopterFlags,	FIELD_INTEGER),
	DEFINE_FIELD( CBaseHelicopter, m_vecDesiredFaceDir,	FIELD_VECTOR ),
	DEFINE_FIELD( CBaseHelicopter, m_vecDesiredPosition,FIELD_POSITION_VECTOR ),
	DEFINE_FIELD( CBaseHelicopter, m_vecGoalOrientation,FIELD_VECTOR ),
	DEFINE_FIELD( CBaseHelicopter, m_flLastSeen,		FIELD_TIME ),
	DEFINE_FIELD( CBaseHelicopter, m_flPrevSeen,		FIELD_TIME ),
//	DEFINE_FIELD( CBaseHelicopter, m_iSoundState,		FIELD_INTEGER ),		// Don't save, precached
	DEFINE_FIELD( CBaseHelicopter, m_vecTarget,			FIELD_VECTOR ),
	DEFINE_FIELD( CBaseHelicopter, m_vecTargetPosition,	FIELD_POSITION_VECTOR ),

	DEFINE_FIELD( CBaseHelicopter, m_flMaxSpeed,		FIELD_FLOAT ),
	DEFINE_FIELD( CBaseHelicopter, m_flMaxSpeedFiring,	FIELD_FLOAT ),
	DEFINE_FIELD( CBaseHelicopter, m_flGoalSpeed,		FIELD_FLOAT ),
	DEFINE_KEYFIELD( CBaseHelicopter, m_flInitialSpeed, FIELD_FLOAT, "InitialSpeed" ),

	// Inputs
	DEFINE_INPUTFUNC( CBaseHelicopter, FIELD_STRING, "ChangePathCorner", InputChangePathCorner),
	DEFINE_INPUTFUNC( CBaseHelicopter, FIELD_VOID, "Activate", InputActivate),

	// Outputs
	DEFINE_OUTPUT(CBaseHelicopter, m_AtTarget,			"AtPathCorner" ),
	DEFINE_OUTPUT(CBaseHelicopter, m_LeaveTarget,		"LeavePathCorner" ),//<<TEMP>> Undone

END_DATADESC()

IMPLEMENT_SERVERCLASS_ST( CBaseHelicopter, DT_BaseHelicopter )
END_SEND_TABLE()


//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
// Notes   : Have your derived Helicopter's Spawn() function call this one FIRST
//------------------------------------------------------------------------------
void CBaseHelicopter::Precache( void )
{
}


//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
// Notes   : Have your derived Helicopter's Spawn() function call this one FIRST
//------------------------------------------------------------------------------
void CBaseHelicopter::Spawn( void )
{
	Precache( );

	SetSolid( SOLID_BBOX );
	SetMoveType( MOVETYPE_STEP );
	AddFlag( FL_FLY );

	m_lifeState			= LIFE_ALIVE;

	// This base class assumes the helicopter has no guns or missiles. 
	// Set the appropriate flags in your derived class' Spawn() function.
	m_fHelicopterFlags &= ~BITS_HELICOPTER_MISSILE_ON;
	m_fHelicopterFlags &= ~BITS_HELICOPTER_GUN_ON;

	m_pRotorSound = NULL;

	m_flCycle = 0;
	ResetSequenceInfo();

	AddFlag( FL_NPC );

	m_flMaxSpeed = BASECHOPPER_MAX_SPEED;
	m_flMaxSpeedFiring = BASECHOPPER_MAX_FIRING_SPEED;
	m_takedamage = DAMAGE_AIM;

	// Don't start up if the level designer has asked the 
	// helicopter to start disabled.
	if ( !(m_spawnflags & SF_AWAITINPUT) )
	{
		Startup();
		SetNextThink( gpGlobals->curtime + 1.0f );
	}

}


//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
bool CBaseHelicopter::FireGun( void )
{
	return true;
}


//------------------------------------------------------------------------------
// Purpose : The main think function for the helicopters
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::HelicopterThink( void )
{
	SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );

	// Don't keep this around for more than one frame.
	ClearCondition( COND_ENEMY_DEAD );

	// Animate and dispatch animation events.
	DispatchAnimEvents( this );

	PrescheduleThink();

	ShowDamage( );

	// -----------------------------------------------
	// If AI is disabled, kill any motion and return
	// -----------------------------------------------
	if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
	{
		SetAbsVelocity( vec3_origin );
		SetLocalAngularVelocity( vec3_angle );
		SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );
		return;
	}

	Hunt();

	HelicopterPostThink();
}



//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::Hunt( void )
{
	FlyPathCorners( );

	if( HasCondition( COND_ENEMY_DEAD ) )
	{
		SetEnemy( NULL );
	}

	// Look for my best enemy. If I change enemies, 
	// be sure and change my prevseen/lastseen timers.
	if( m_lifeState == LIFE_ALIVE )
	{
		GetSenses()->Look( 4092 );

		ChooseEnemy();

		if( HasEnemy() )
		{
			CheckEnemy( GetEnemy() );

			if (FVisible( GetEnemy() ))
			{
				if (m_flLastSeen < gpGlobals->curtime - 2)
				{
					m_flPrevSeen = gpGlobals->curtime;
				}

				m_flLastSeen = gpGlobals->curtime;
				m_vecTargetPosition = GetEnemy()->WorldSpaceCenter();
			}
		}
		else
		{
			// look at where we're going instead
			m_vecTargetPosition = m_vecDesiredPosition;
		}
	}
	else
	{
		// If we're dead or dying, forget our enemy and don't look for new ones(sjb)
		SetEnemy( NULL );
	}

	if ( 1 )
	{
		Vector targetDir = m_vecTargetPosition - GetAbsOrigin();
		Vector desiredDir = m_vecDesiredPosition - GetAbsOrigin();

		VectorNormalize( targetDir ); 
		VectorNormalize( desiredDir ); 

		if ( !IsCrashing() && m_flLastSeen + 5 > gpGlobals->curtime ) //&& DotProduct( targetDir, desiredDir) > 0.25)
		{
			// If we've seen the target recently, face the target.
			//Msg( "Facing Target \n" );
			m_vecDesiredFaceDir = targetDir;
		}
		else
		{
			// Face our desired position.
			// Msg( "Facing Position\n" );
			m_vecDesiredFaceDir = desiredDir;
		}
	}
	else
	{
		// Face the way the path corner tells us to.
		//Msg( "Facing my path corner\n" );
		m_vecDesiredFaceDir = m_vecGoalOrientation;
	}

	Flight();

	UpdatePlayerDopplerShift( );

	// ALERT( at_console, "%.0f %.0f %.0f\n", gpGlobals->curtime, m_flLastSeen, m_flPrevSeen );
	if (m_fHelicopterFlags & BITS_HELICOPTER_GUN_ON)
	{
		//if ( (m_flLastSeen + 1 > gpGlobals->curtime) && (m_flPrevSeen + 2 < gpGlobals->curtime) )
		{
			if (FireGun( ))
			{
				// slow down if we're firing
				if (m_flGoalSpeed > m_flMaxSpeedFiring )
				{
					m_flGoalSpeed = m_flMaxSpeedFiring;
				}
			}
		}
	}

	if (m_fHelicopterFlags & BITS_HELICOPTER_MISSILE_ON)
	{
		AimRocketGun();
	}

	// Finally, forget dead enemies.
	if( GetEnemy() != NULL && !GetEnemy()->IsAlive() )
	{
		SetEnemy( NULL );
	}
}



//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::FlyPathCorners( void )
{

	if ( m_pGoalEnt == NULL && m_target != NULL_STRING )// this monster has a target
	{
		m_pGoalEnt = gEntList.FindEntityByName( NULL, m_target, NULL );
		if (m_pGoalEnt)
		{
			m_vecDesiredPosition = m_pGoalEnt->GetLocalOrigin();

			// FIXME: orienation removed from path_corners!
			AngleVectors( m_pGoalEnt->GetLocalAngles(), &m_vecGoalOrientation );
		}
	}

	// walk route
	if (m_pGoalEnt)
	{
		// ALERT( at_console, "%.0f\n", flLength );
		if ( HasReachedTarget( ) )
		{
			// If we get this close to the desired position, it's assumed that we've reached
			// the desired position, so move on.

			// Fire target that I've reached my goal
			m_AtTarget.FireOutput( m_pGoalEnt, this );

			OnReachedTarget( m_pGoalEnt );

			m_pGoalEnt = gEntList.FindEntityByName( NULL, m_pGoalEnt->m_target, NULL );

			if (m_pGoalEnt)
			{
				m_vecDesiredPosition = m_pGoalEnt->GetAbsOrigin();
			
				// FIXME: orienation removed from path_corners!
				AngleVectors( m_pGoalEnt->GetLocalAngles(), &m_vecGoalOrientation );

				// NDebugOverlay::Box( m_vecDesiredPosition, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0,255,0, false, 30.0);
			}
		}
	}
	else
	{
		// If we can't find a new target, just stay where we are.
		m_vecDesiredPosition = GetAbsOrigin();
	}

}


//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::UpdatePlayerDopplerShift( )
{
	// -----------------------------
	// make rotor, engine sounds
	// -----------------------------
	if (m_iSoundState == 0)
	{
		// Sound startup.
		InitializeRotorSound();
	}
	else
	{
		CBaseEntity *pPlayer = NULL;

		// UNDONE: this needs to send different sounds to every player for multiplayer.	
		// FIXME: this isn't the correct way to find a player!!!
		pPlayer = gEntList.FindEntityByName( NULL, "!player", this );
		if (pPlayer)
		{
			Vector dir = pPlayer->GetLocalOrigin() - GetLocalOrigin();
			VectorNormalize(dir);

			float velReceiver = -DotProduct( pPlayer->GetAbsVelocity(), dir );
			float velTransmitter = -DotProduct( GetAbsVelocity(), dir );
			// speed of sound == 13049in/s
			int iPitch = 100 * ((1 - velReceiver / 13049) / (1 + velTransmitter / 13049));

			// clamp pitch shifts
			if (iPitch > 250) 
				iPitch = 250;
			if (iPitch < 50)
				iPitch = 50;

			// Msg( "Pitch:%d\n", iPitch );

			UpdateRotorSoundPitch( iPitch );
			//Msg( "%.0f\n", pitch );
			//Msg( "%.0f\n", flVol );
		}
		else
		{
			Msg( "Chopper didn't find a player!\n" );
		}
	}
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void CBaseHelicopter::Flight( void )
{
	if( GetFlags() & FL_ONGROUND )
	{
		//This would be really bad.
		RemoveFlag( FL_ONGROUND );
	}

	// Generic speed up
	if (m_flGoalSpeed < m_flMaxSpeed)
	{
		m_flGoalSpeed += GetAcceleration();
	}
	
//	NDebugOverlay::Line(GetAbsOrigin(), m_vecDesiredPosition, 0,0,255, true, 0.1);

	// estimate where I'll be facing in one seconds
	Vector forward, right, up;
	AngleVectors( GetLocalAngles() + GetLocalAngularVelocity() * 2, &forward, &right, &up );

	QAngle angVel = GetLocalAngularVelocity();
	float flSide = DotProduct( m_vecDesiredFaceDir, right );
	if (flSide < 0)
	{
		if ( angVel.y < 8 )
		{
			angVel.y += 2;
		}
		else if (angVel.y < 60)
		{
			angVel.y += 8;
		}
	}
	else
	{
		if ( angVel.y > -8 )
		{
			angVel.y -= 2;
		}
		else if (angVel.y > -60)
		{
			angVel.y -= 8;
		}
	}

	angVel.y *= ( 0.98 ); // why?! (sjb)

	// estimate where I'll be in two seconds
	AngleVectors( GetLocalAngles() + angVel, NULL, NULL, &up );
	Vector vecEst = GetAbsOrigin() + GetAbsVelocity() * 2.0 + up * m_flForce * 20 - Vector( 0, 0, 384 * 2 );

	// add immediate force
	AngleVectors( GetLocalAngles(), &forward, &right, &up );
	
	Vector vecImpulse( 0, 0, 0 );
	vecImpulse.x += up.x * m_flForce;
	vecImpulse.y += up.y * m_flForce;
	vecImpulse.z += up.z * m_flForce;

	// add gravity
	vecImpulse.z -= 38.4; // 32ft/sec
	ApplyAbsVelocityImpulse( vecImpulse );

	float flSpeed = GetAbsVelocity().Length();
	float flDir = DotProduct( Vector( forward.x, forward.y, 0 ), Vector( GetAbsVelocity().x, GetAbsVelocity().y, 0 ) );
	if (flDir < 0)
	{
		flSpeed = -flSpeed;
	}

	float flDist = DotProduct( m_vecDesiredPosition - vecEst, forward );

//	float flDist = (m_vecDesiredPosition - vecEst).Length();

	// float flSlip = DotProduct( GetAbsVelocity(), right );
	float flSlip = -DotProduct( m_vecDesiredPosition - vecEst, right );

	// fly sideways
	if (flSlip > 0)
	{
		if (GetLocalAngles().z > -30 && angVel.z > -15)
			angVel.z -= 4;
		else
			angVel.z += 2;
	}
	else
	{
		if (GetLocalAngles().z < 30 && angVel.z < 15)
			angVel.z += 4;
		else
			angVel.z -= 2;
	}

	// These functions contain code Ken wrote that used to be right here as part of the flight model,
	// but we want different helicopter vehicles to have different drag characteristics, so I made
	// them virtual functions (sjb)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -