📄 hl1_npc_osprey.cpp
字号:
ApplySidewaysDrag( right );
ApplyGeneralDrag();
// apply power to stay correct height
// FIXME: these need to be per class variables
#define MAX_FORCE 80
#define FORCE_POSDELTA 12
#define FORCE_NEGDELTA 8
if (m_flForce < MAX_FORCE && vecEst.z < m_vecDesiredPosition.z)
{
m_flForce += FORCE_POSDELTA;
}
else if (m_flForce > 30)
{
if (vecEst.z > m_vecDesiredPosition.z)
m_flForce -= FORCE_NEGDELTA;
}
// pitch forward or back to get to target
//-----------------------------------------
// Pitch is reversed since Half-Life! (sjb)
//-----------------------------------------
// when we're way out, lean forward up to 40 degrees to accelerate to target
// not exceeding our goal speed.
#if 0
float nodeSpeed = m_pGoalEnt->m_flSpeed;
if ( flDist > 300 && flSpeed < m_flGoalSpeed && GetLocalAngles().x + angVel.x < 25 )
{
angVel.x += 8.0; //lean forward
}
else if ( flDist < 500 && GetLocalAngles().x + angVel.x > -30 && nodeSpeed == 0)
{
angVel.x -= 8.0; // lean backwards as we approach the target
}
else if (GetLocalAngles().x + angVel.x < -20 )
{
// ALERT( at_console, "f " );
angVel.x += 2.0;
}
else if (GetLocalAngles().x + angVel.x > 20 )
{
// ALERT( at_console, "b " );
angVel.x -= 2.0;
}
#else
m_angleVelocity = GetLocalAngles().x + angVel.x;
float angleX = angVel.x;
// Msg("AngVel %f, %f\n", m_angleVelocity, flDist);
if (flDist > 128 && flSpeed < m_flGoalSpeed && m_angleVelocity < 30)
{
// ALERT( at_console, "F " );
// lean forward
angleX += 12.0;
}
else if (flDist < -128 && flSpeed > -50 && m_angleVelocity > -20)
{
// ALERT( at_console, "B " );
// lean backward
angleX -= 12.0;
}
else if ( (m_angleVelocity < -20) || (m_angleVelocity < 0 && flDist < 128) )
{
// ALERT( at_console, "f " );
if ( abs(m_angleVelocity) < 5 )
{
angleX += 1.0;
}
else
{
angleX += 4.0;
}
}
else if ( (m_angleVelocity > 20) || (m_angleVelocity > 0 && flDist < 128) )
{
// ALERT( at_console, "b " );
if ( abs(m_angleVelocity) < 5 )
{
angleX -= 1.0;
}
else
{
angleX -= 4.0;
}
}
angVel.x = angleX;
//Msg("AngVel.x %f %f\n", angVel.x, angleX );
#endif
SetLocalAngularVelocity( angVel );
// ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", GetAbsOrigin().x, GetAbsVelocity().x, flDist, flSpeed, GetLocalAngles().x, m_vecAngVelocity.x, m_flForce );
// ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", GetAbsOrigin().z, GetAbsVelocity().z, vecEst.z, m_vecDesiredPosition.z, m_flForce );
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::InitializeRotorSound( void )
{
if (m_pRotorSound)
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
// Get the rotor sound started up.
controller.Play( m_pRotorSound, 0.0, 100 );
controller.SoundChangeVolume(m_pRotorSound, GetRotorVolume(), 2.0);
}
m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::UpdateRotorSoundPitch( int iPitch )
{
if (m_pRotorSound)
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
controller.SoundChangePitch( m_pRotorSound, iPitch, 0.1 );
controller.SoundChangeVolume( m_pRotorSound, GetRotorVolume(), 0.1 );
}
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::FlyTouch( CBaseEntity *pOther )
{
// bounce if we hit something solid
if ( pOther->GetSolid() == SOLID_BSP)
{
trace_t tr = CBaseEntity::GetTouchTrace( );
// UNDONE, do a real bounce
ApplyAbsVelocityImpulse( tr.plane.normal * (GetAbsVelocity().Length() + 200) );
}
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::CrashTouch( CBaseEntity *pOther )
{
// only crash if we hit something solid
if ( pOther->GetSolid() == SOLID_BSP)
{
SetTouch( NULL );
SetNextThink( gpGlobals->curtime );
Vector position = GetAbsOrigin();
position.z += 32;
CPASFilter filter( GetAbsOrigin() );
for (int i = 0; i < 7; i++)
{
te->Explosion( filter, i * 0.2, &GetAbsOrigin(), g_sModelIndexFireball, 10, 15, TE_EXPLFLAG_NONE, 100, 0 );
position.z += 15;
}
UTIL_Remove( this );
}
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::DyingThink( void )
{
StudioFrameAdvance( );
SetNextThink( gpGlobals->curtime + 0.1f );
SetLocalAngularVelocity( GetLocalAngularVelocity() * 1.02 );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
int CBaseHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
{
#if 0
// This code didn't port easily. WTF does it do? (sjb)
if (pevInflictor->m_owner == pev)
return 0;
#endif
/*
if ( (bitsDamageType & DMG_BULLET) && flDamage > 50)
{
// clip bullet damage at 50
flDamage = 50;
}
*/
return BaseClass::OnTakeDamage_Alive( info );
}
//-----------------------------------------------------------------------------
// Purpose: Override base class to add display of fly direction
// Input :
// Output :
//-----------------------------------------------------------------------------
void CBaseHelicopter::DrawDebugGeometryOverlays(void)
{
if (m_pfnThink!= NULL)
{
// ------------------------------
// Draw route if requested
// ------------------------------
if (m_debugOverlays & OVERLAY_NPC_ROUTE_BIT)
{
NDebugOverlay::Line(GetAbsOrigin(), m_vecDesiredPosition, 0,0,255, true, 0);
}
}
BaseClass::DrawDebugGeometryOverlays();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CBaseHelicopter::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
{
CTakeDamageInfo dmgInfo = info;
// ALERT( at_console, "%d %.0f\n", ptr->iHitgroup, flDamage );
// HITGROUPS don't work currently.
// ignore blades
// if (ptr->hitgroup == 6 && (info.GetDamageType() & (DMG_ENERGYBEAM|DMG_BULLET|DMG_CLUB)))
// return;
// hit hard, hits cockpit
if (info.GetDamage() > 50 || ptr->hitgroup == 11 )
{
// ALERT( at_console, "%map .0f\n", flDamage );
AddMultiDamage( dmgInfo, this );
// m_iDoSmokePuff = 3 + (info.GetDamage() / 5.0);
}
else
{
// do half damage in the body
dmgInfo.ScaleDamage(0.5);
AddMultiDamage( dmgInfo, this );
g_pEffects->Ricochet( ptr->endpos, ptr->plane.normal );
}
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CBaseHelicopter::NullThink( void )
{
StudioFrameAdvance( );
SetNextThink( gpGlobals->curtime + 0.5f );
}
void CBaseHelicopter::Startup( void )
{
m_flGoalSpeed = m_flInitialSpeed;
SetThink( HelicopterThink );
SetTouch( FlyTouch );
SetNextThink( gpGlobals->curtime + 0.1f );
}
void CBaseHelicopter::Event_Killed( const CTakeDamageInfo &info )
{
m_lifeState = LIFE_DYING;
SetMoveType( MOVETYPE_FLYGRAVITY );
SetGravity( 0.3 );
// Kill the rotor sound.
UTIL_SetSize( this, Vector( -32, -32, -64), Vector( 32, 32, 0) );
SetThink( CallDyingThink );
SetTouch( CrashTouch );
SetNextThink( gpGlobals->curtime + 0.1f );
m_iHealth = 0;
m_takedamage = DAMAGE_NO;
/*
if (m_spawnflags & SF_NOWRECKAGE)
{
m_flNextRocket = gpGlobals->curtime + 4.0;
}
else
{
m_flNextRocket = gpGlobals->curtime + 15.0;
}
*/
m_OnDeath.FireOutput( info.GetAttacker(), this );
}
void CBaseHelicopter::StopLoopingSounds()
{
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
controller.SoundDestroy( m_pRotorSound );
m_pRotorSound = NULL;
BaseClass::StopLoopingSounds();
}
void CBaseHelicopter::GibMonster( void )
{
}
void CBaseHelicopter::ChangePathCorner( const char *pszName )
{
if( m_lifeState != LIFE_ALIVE )
{
// Disregard this if dead or dying.
return;
}
if (m_pGoalEnt)
{
m_pGoalEnt = gEntList.FindEntityByName( NULL, pszName, this );
// I don't think we need to do this. The FLIGHT() code will do it for us (sjb)
if (m_pGoalEnt)
{
m_vecDesiredPosition = m_pGoalEnt->GetLocalOrigin();
AngleVectors( m_pGoalEnt->GetLocalAngles(), &m_vecGoalOrientation );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Slams the chopper's current path corner and sends it to a new one.
// This code does NOT check that the path from the current position
// to the wished path corner is clear!
//-----------------------------------------------------------------------------
void CBaseHelicopter::InputChangePathCorner( inputdata_t &inputdata )
{
ChangePathCorner( inputdata.value.String() );
}
//-----------------------------------------------------------------------------
// Purpose: Call Startup for a helicopter that's been flagged to start disabled
//-----------------------------------------------------------------------------
void CBaseHelicopter::InputActivate( inputdata_t &inputdata )
{
if( m_spawnflags & SF_AWAITINPUT )
{
Startup();
// Now clear the spawnflag to protect from
// subsequent calls.
m_spawnflags &= ~SF_AWAITINPUT;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CBaseHelicopter::ApplySidewaysDrag( const Vector &vecRight )
{
Vector vecNewVelocity = GetAbsVelocity();
vecNewVelocity.x *= 1.0 - fabs( vecRight.x ) * 0.05;
vecNewVelocity.y *= 1.0 - fabs( vecRight.y ) * 0.05;
vecNewVelocity.z *= 1.0 - fabs( vecRight.z ) * 0.05;
SetAbsVelocity( vecNewVelocity );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CBaseHelicopter::ApplyGeneralDrag( void )
{
Vector vecNewVelocity = GetAbsVelocity();
vecNewVelocity *= 0.995;
SetAbsVelocity( vecNewVelocity );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CBaseHelicopter::ChooseEnemy( void )
{
// See if there's a new enemy.
CBaseEntity *pNewEnemy;
pNewEnemy = BestEnemy();
if( ( pNewEnemy != GetEnemy() ) && pNewEnemy != NULL )
{
//New enemy! Clear the timers and set conditions.
SetCondition(COND_NEW_ENEMY);
SetEnemy( pNewEnemy );
m_flLastSeen = m_flPrevSeen = gpGlobals->curtime;
return true;
}
else
{
ClearCondition( COND_NEW_ENEMY );
return false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CBaseHelicopter::CheckEnemy( CBaseEntity *pEnemy )
{
// -------------------
// If enemy is dead
// -------------------
if ( !pEnemy->IsAlive() )
{
SetCondition( COND_ENEMY_DEAD );
ClearCondition( COND_SEE_ENEMY );
ClearCondition( COND_ENEMY_OCCLUDED );
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -