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

📄 hl1_npc_turret.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		
		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 + -