📄 hl1_npc_turret.cpp
字号:
if (flDist > 180)
{
flDist = 360 - flDist;
flDir = -flDir;
}
if (flDist > 30)
{
if (m_fTurnRate < m_iBaseTurnRate * 10)
{
m_fTurnRate += m_iBaseTurnRate;
}
}
else if (m_fTurnRate > 45)
{
m_fTurnRate -= m_iBaseTurnRate;
}
else
{
m_fTurnRate += m_iBaseTurnRate;
}
m_vecCurAngles.y += 0.1 * m_fTurnRate * flDir;
if (m_vecCurAngles.y < 0)
m_vecCurAngles.y += 360;
else if (m_vecCurAngles.y >= 360)
m_vecCurAngles.y -= 360;
if (flDist < (0.05 * m_iBaseTurnRate))
m_vecCurAngles.y = m_vecGoalAngles.y;
QAngle angles = GetAbsAngles();
//ALERT(at_console, "%.2f -> %.2f\n", m_vecCurAngles.y, y);
if (m_iOrientation == TURRET_ORIENTATION_FLOOR)
SetBoneController(0, m_vecCurAngles.y - angles.y );
else
SetBoneController(0, angles.y - 180 - m_vecCurAngles.y );
bMoved = 1;
}
if (!bMoved)
m_fTurnRate = m_iBaseTurnRate;
//DevMsg(1, "(%.2f, %.2f)->(%.2f, %.2f)\n", m_vecCurAngles.x,
// m_vecCurAngles.y, m_vecGoalAngles.x, m_vecGoalAngles.y);
return bMoved;
}
void CNPC_BaseTurret::TurretUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !ShouldToggle( useType, m_iOn ) )
return;
if (m_iOn)
{
SetEnemy( NULL );
SetNextThink( gpGlobals->curtime + 0.1 );
m_iAutoStart = FALSE;// switching off a turret disables autostart
//!!!! this should spin down first!!BUGBUG
SetThink(&CNPC_BaseTurret::Retire);
}
else
{
SetNextThink( gpGlobals->curtime + 0.1 ); // turn on delay
// if the turret is flagged as an autoactivate turret, re-enable it's ability open self.
if ( m_spawnflags & SF_MONSTER_TURRET_AUTOACTIVATE )
{
m_iAutoStart = TRUE;
}
SetThink(&CNPC_BaseTurret::Deploy);
}
}
void CNPC_BaseTurret::InputDeactivate( inputdata_t &inputdata )
{
if( m_iOn && m_lifeState == LIFE_ALIVE )
{
SetEnemy( NULL );
SetNextThink( gpGlobals->curtime + 0.1 );
m_iAutoStart = FALSE;// switching off a turret disables autostart
//!!!! this should spin down first!!BUGBUG
SetThink(&CNPC_BaseTurret::Retire);
}
}
void CNPC_BaseTurret::InputActivate( inputdata_t &inputdata )
{
if( !m_iOn && m_lifeState == LIFE_ALIVE )
{
SetNextThink( gpGlobals->curtime + 0.1 ); // turn on delay
// if the turret is flagged as an autoactivate turret, re-enable it's ability open self.
if ( m_spawnflags & SF_MONSTER_TURRET_AUTOACTIVATE )
{
m_iAutoStart = TRUE;
}
SetThink(&CNPC_BaseTurret::Deploy);
}
}
//=========================================================
// EyeOn - turn on light on the turret
//=========================================================
void CNPC_BaseTurret::EyeOn(void)
{
if (m_pEyeGlow)
{
if (m_eyeBrightness != 255)
{
m_eyeBrightness = 255;
}
m_pEyeGlow->SetBrightness( m_eyeBrightness );
}
}
//=========================================================
// EyeOn - turn off light on the turret
//=========================================================
void CNPC_BaseTurret::EyeOff(void)
{
if (m_pEyeGlow)
{
if (m_eyeBrightness > 0)
{
m_eyeBrightness = max( 0, m_eyeBrightness - 30 );
m_pEyeGlow->SetBrightness( m_eyeBrightness );
}
}
}
void CNPC_BaseTurret::Event_Killed( const CTakeDamageInfo &info )
{
BaseClass::Event_Killed( info );
SetMoveType( MOVETYPE_FLY );
}
//===
class CNPC_MiniTurret : public CNPC_BaseTurret
{
DECLARE_CLASS( CNPC_MiniTurret, CNPC_BaseTurret );
public:
void Spawn( );
void Precache(void);
// other functions
void Shoot(Vector &vecSrc, Vector &vecDirToEnemy);
};
class CNPC_Turret : public CNPC_BaseTurret
{
DECLARE_CLASS( CNPC_Turret, CNPC_BaseTurret );
public:
void Spawn(void);
void Precache(void);
// Think functions
void SpinUpCall(void);
void SpinDownCall(void);
// other functions
void Shoot(Vector &vecSrc, Vector &vecDirToEnemy);
private:
int m_iStartSpin;
};
LINK_ENTITY_TO_CLASS( monster_turret, CNPC_Turret );
LINK_ENTITY_TO_CLASS( monster_miniturret, CNPC_MiniTurret );
ConVar sk_turret_health ( "sk_turret_health","50");
ConVar sk_miniturret_health ( "sk_miniturret_health","40");
ConVar sk_sentry_health ( "sk_sentry_health","40");
void CNPC_Turret::Spawn()
{
Precache( );
SetModel( "models/turret.mdl" );
m_iHealth = sk_turret_health.GetFloat();
m_HackedGunPos = Vector( 0, 0, 12.75 );
m_flMaxSpin = TURRET_MAXSPIN;
Vector view_ofs( 0, 0, 12.75 );
SetViewOffset( view_ofs );
CNPC_BaseTurret::Spawn( );
m_iRetractHeight = 16;
m_iDeployHeight = 32;
m_iMinPitch = -90;
UTIL_SetSize(this, Vector(-32, -32, -m_iRetractHeight), Vector(32, 32, m_iRetractHeight));
SetThink(&CNPC_BaseTurret::Initialize);
m_pEyeGlow = CSprite::SpriteCreate( TURRET_GLOW_SPRITE, GetAbsOrigin(), FALSE );
m_pEyeGlow->SetTransparency( kRenderGlow, 255, 0, 0, 0, kRenderFxNoDissipation );
m_pEyeGlow->SetAttachment( this, 2 );
m_eyeBrightness = 0;
SetNextThink( gpGlobals->curtime + 0.3 );
}
void CNPC_Turret::Precache()
{
CNPC_BaseTurret::Precache( );
engine->PrecacheModel ("models/turret.mdl");
engine->PrecacheModel (TURRET_GLOW_SPRITE);
engine->PrecacheModel( "sprites/xspark4.vmt" );
//precache sounds
}
void CNPC_Turret::Shoot(Vector &vecSrc, Vector &vecDirToEnemy)
{
CPASAttenuationFilter filter( this );
FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 );
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "turret/tu_fire1.wav", TURRET_MACHINE_VOLUME, 0.6 );
m_fEffects |= EF_MUZZLEFLASH;
}
void CNPC_Turret::SpinUpCall(void)
{
StudioFrameAdvance( );
SetNextThink( gpGlobals->curtime + 0.1 );
// Are we already spun up? If not start the two stage process.
if (!m_iSpin)
{
SetTurretAnim(TURRET_ANIM_SPIN);
// for the first pass, spin up the the barrel
if (!m_iStartSpin)
{
SetNextThink( gpGlobals->curtime + 1.0 ); //spinup delay
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_BODY, "turret/tu_spinup.wav", TURRET_MACHINE_VOLUME, ATTN_NORM );
m_iStartSpin = 1;
m_flPlaybackRate = 0.1;
}
// after the barrel is spun up, turn on the hum
else if (m_flPlaybackRate >= 1.0)
{
SetNextThink( gpGlobals->curtime + 0.1 );// retarget delay
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_STATIC, "turret/tu_active2.wav", TURRET_MACHINE_VOLUME, ATTN_NORM );
SetThink(&CNPC_BaseTurret::ActiveThink);
m_iStartSpin = 0;
m_iSpin = 1;
}
else
{
m_flPlaybackRate += 0.075;
}
}
if (m_iSpin)
{
SetThink(&CNPC_BaseTurret::ActiveThink);
}
}
void CNPC_Turret::SpinDownCall(void)
{
if (m_iSpin)
{
CPASAttenuationFilter filter( this );
SetTurretAnim(TURRET_ANIM_SPIN);
if ( m_flPlaybackRate == 1.0)
{
enginesound->StopSound( entindex(), CHAN_WEAPON, "turret/tu_active2.wav" );
enginesound->EmitSound( filter, entindex(), CHAN_ITEM, "turret/tu_spindown.wav", TURRET_MACHINE_VOLUME, ATTN_NORM, 0, PITCH_NORM + random->RandomInt(-10,10) );
}
m_flPlaybackRate -= 0.02;
if (m_flPlaybackRate <= 0)
{
m_flPlaybackRate = 0;
m_iSpin = 0;
}
}
}
void CNPC_MiniTurret::Spawn()
{
Precache( );
SetModel( "models/miniturret.mdl" );
m_iHealth = sk_miniturret_health.GetFloat();
m_HackedGunPos = Vector( 0, 0, 12.75 );
m_flMaxSpin = 0;
Vector view_ofs( 0, 0, 12.75 );
SetViewOffset( view_ofs );
CNPC_BaseTurret::Spawn( );
m_iRetractHeight = 16;
m_iDeployHeight = 32;
m_iMinPitch = -90;
UTIL_SetSize(this, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight));
SetThink(&CNPC_MiniTurret::Initialize);
SetNextThink(gpGlobals->curtime + 0.3);
if (( m_spawnflags & SF_MONSTER_TURRET_AUTOACTIVATE ) && !( m_spawnflags & SF_MONSTER_TURRET_STARTINACTIVE ))
{
m_iAutoStart = true;
}
}
void CNPC_MiniTurret::Precache()
{
CNPC_BaseTurret::Precache( );
m_iAmmoType = GetAmmoDef()->Index("9mmRound");
engine->PrecacheModel ("models/miniturret.mdl");
enginesound->PrecacheSound("weapons/hks1.wav");
enginesound->PrecacheSound("weapons/hks2.wav");
enginesound->PrecacheSound("weapons/hks3.wav");
}
void CNPC_MiniTurret::Shoot(Vector &vecSrc, Vector &vecDirToEnemy)
{
FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 );
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "turret/tu_fire1.wav", TURRET_MACHINE_VOLUME, 1 );
m_fEffects |= EF_MUZZLEFLASH;
}
//=========================================================
// Sentry gun - smallest turret, placed near grunt entrenchments
//=========================================================
class CNPC_Sentry : public CNPC_BaseTurret
{
DECLARE_CLASS( CNPC_Sentry, CNPC_BaseTurret );
public:
void Spawn( );
void Precache(void);
// other functions
void Shoot(Vector &vecSrc, Vector &vecDirToEnemy);
int OnTakeDamage_Alive(const CTakeDamageInfo &info);
void Event_Killed( const CTakeDamageInfo &info );
void SentryTouch( CBaseEntity *pOther );
DECLARE_DATADESC();
};
BEGIN_DATADESC( CNPC_Sentry )
DEFINE_ENTITYFUNC( CNPC_Sentry, SentryTouch ),
END_DATADESC()
LINK_ENTITY_TO_CLASS( monster_sentry, CNPC_Sentry );
void CNPC_Sentry::Precache()
{
BaseClass::Precache( );
m_iAmmoType = GetAmmoDef()->Index("9mmRound");
engine->PrecacheModel ("models/sentry.mdl");
enginesound->PrecacheSound("weapons/hks1.wav");
enginesound->PrecacheSound("weapons/hks2.wav");
enginesound->PrecacheSound("weapons/hks3.wav");
}
void CNPC_Sentry::Spawn()
{
Precache( );
SetModel( "models/sentry.mdl" );
m_iHealth = sk_sentry_health.GetFloat();
m_HackedGunPos = Vector( 0, 0, 48 );
SetViewOffset( Vector(0,0,48) );
m_flMaxWait = 1E6;
m_flMaxSpin = 1E6;
BaseClass::Spawn();
SetSequence( TURRET_ANIM_RETIRE );
m_flCycle = 0.0;
m_flPlaybackRate = 0.0;
m_iRetractHeight = 64;
m_iDeployHeight = 64;
m_iMinPitch = -60;
UTIL_SetSize(this, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight));
SetTouch(&CNPC_Sentry::SentryTouch);
SetThink(&CNPC_Sentry::Initialize);
SetNextThink(gpGlobals->curtime + 0.3);
}
void CNPC_Sentry::Shoot(Vector &vecSrc, Vector &vecDirToEnemy)
{
FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 );
CPASAttenuationFilter filter( this );
switch(random->RandomInt(0,2))
{
case 0:
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/hks1.wav", TURRET_MACHINE_VOLUME, 1 );
break;
case 1:
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/hks2.wav", TURRET_MACHINE_VOLUME, 1 );
break;
case 2:
default:
enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/hks3.wav", TURRET_MACHINE_VOLUME, 1 );
break;
}
SETBITS( m_fEffects, EF_MUZZLEFLASH );
}
int CNPC_Sentry::OnTakeDamage_Alive(const CTakeDamageInfo &info)
{
if ( m_takedamage == DAMAGE_NO )
return 0;
if (!m_iOn)
{
SetThink( &CNPC_Sentry::Deploy );
SetUse( NULL );
SetNextThink( gpGlobals->curtime + 0.1 );
}
return BaseClass::OnTakeDamage_Alive( info );
}
void CNPC_Sentry::Event_Killed( const CTakeDamageInfo &info )
{
CPASAttenuationFilter filter( this );
switch( random->RandomInt(0,2) )
{
case 0:
enginesound->EmitSound( filter, entindex(), CHAN_BODY, "turret/tu_die.wav", TURRET_MACHINE_VOLUME, ATTN_NORM );
break;
case 1:
enginesound->EmitSound( filter, entindex(), CHAN_BODY, "turret/tu_die2.wav", TURRET_MACHINE_VOLUME, ATTN_NORM );
break;
case 2:
default:
enginesound->EmitSound( filter, entindex(), CHAN_BODY, "turret/tu_die3.wav", TURRET_MACHINE_VOLUME, ATTN_NORM );
break;
}
enginesound->StopSound( entindex(), CHAN_STATIC, "turret/tu_active2.wav" );
SetSolidFlags( FSOLID_NOT_STANDABLE );
Vector vecSrc;
QAngle vecAng;
GetAttachment( 2, vecSrc, vecAng );
te->Smoke( filter, 0.0, &vecSrc,
g_sModelIndexSmoke,
2.5,
10 );
g_pEffects->Sparks( vecSrc );
BaseClass::Event_Killed( info );
}
void CNPC_Sentry::SentryTouch( CBaseEntity *pOther )
{
//trigger the sentry to turn on if a monster or player touches it
if ( pOther && (pOther->IsPlayer() || FBitSet ( pOther->GetFlags(), FL_NPC )) )
{
CTakeDamageInfo info;
info.SetAttacker( pOther );
info.SetInflictor( pOther );
info.SetDamage( 0 );
TakeDamage(info);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -