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

📄 hl1_npc_gargantua.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		else
			m_pFlame[i] = CBeam::BeamCreate( GARG_BEAM_SPRITE2, 14.0 );
		if ( m_pFlame[i] )
		{
			int attach = i%2;
			// attachment is 0 based in GetAttachment
			GetAttachment( attach+1, posGun, angleGun );

			Vector vecEnd = ( vForward * GARG_FLAME_LENGTH) + posGun;
			//UTIL_TraceLine( posGun, vecEnd, dont_ignore_monsters, edict(), &trace );

			UTIL_TraceLine ( posGun, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);
//			NDebugOverlay::Line( posGun, vecEnd, 255, 255, 255, false, 10.0f );

			m_pFlame[i]->PointEntInit( trace.endpos, this );
			if ( i < 2 )
				m_pFlame[i]->SetColor( 255, 130, 90 );
			else
				m_pFlame[i]->SetColor( 0, 120, 255 );
			m_pFlame[i]->SetBrightness( 190 );
			m_pFlame[i]->SetBeamFlags( FBEAM_SHADEIN );
			m_pFlame[i]->SetScrollRate( 20 );
			// attachment is 1 based in SetEndAttachment
			m_pFlame[i]->SetEndAttachment( attach + 2 );
			CSoundEnt::InsertSound( SOUND_COMBAT, posGun, 384, 0.3 );
		}
	}

	CPASAttenuationFilter filter4( this );
	enginesound->EmitSound( filter4, entindex(), CHAN_BODY, pBeamAttackSounds[ 1 ], 1, ATTN_NORM, 0, PITCH_NORM );
	enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, pBeamAttackSounds[ 2 ], 1, ATTN_NORM, 0, PITCH_NORM );
}


void CNPC_Gargantua::FlameControls( float angleX, float angleY )
{
	if ( angleY < -180 )
		angleY += 360;
	else if ( angleY > 180 )
		angleY -= 360;

	if ( angleY < -45 )
		angleY = -45;
	else if ( angleY > 45 )
		angleY = 45;

	m_flameX = UTIL_ApproachAngle( angleX, m_flameX, 4 );
	m_flameY = UTIL_ApproachAngle( angleY, m_flameY, 8 );
	SetBoneController( 0, m_flameY );
	SetBoneController( 1, m_flameX );
}


void CNPC_Gargantua::FlameUpdate( void )
{
	int				i;
	static float	offset[2] = { 60, -60 };
	trace_t			trace;
	Vector			vecStart;
	QAngle			angleGun;
	BOOL			streaks = FALSE;

	Vector			vForward;

	for ( i = 0; i < 2; i++ )
	{
		if ( m_pFlame[i] )
		{
			QAngle vecAim = GetAbsAngles();
			vecAim.x += -m_flameX;
			vecAim.y += m_flameY;

			AngleVectors( vecAim, &vForward );

			GetAttachment( i + 2, vecStart, angleGun );
			Vector vecEnd = vecStart + ( vForward * GARG_FLAME_LENGTH); //  - offset[i] * gpGlobals->v_right;
			
			UTIL_TraceLine ( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);

			m_pFlame[i]->SetStartPos( trace.endpos );
			m_pFlame[i+2]->SetStartPos( (vecStart * 0.6) + (trace.endpos * 0.4) );

			if ( trace.fraction != 1.0 && gpGlobals->curtime > m_streakTime )
			{
				g_pEffects->Sparks( trace.endpos, 1, 1, &trace.plane.normal );
				streaks = TRUE;
				UTIL_DecalTrace( &trace, "SmallScorch" );
			}
			// RadiusDamage( trace.vecEndPos, pev, pev, gSkillData.gargantuaDmgFire, CLASS_ALIEN_MONSTER, DMG_BURN );
			FlameDamage( vecStart, trace.endpos, this, this, sk_gargantua_dmg_fire.GetFloat(), CLASS_ALIEN_MONSTER, DMG_BURN );

			CBroadcastRecipientFilter filter;
			GetAttachment(i + 2, vecStart, angleGun);
			te->DynamicLight( filter, 0.0, &vecStart, 255, 0, 0, 0, 48, 0.2, 150 );
		}
	}
	if ( streaks )
		m_streakTime = gpGlobals->curtime;
}



void CNPC_Gargantua::FlameDamage( Vector vecStart, Vector vecEnd, CBaseEntity *pevInflictor, CBaseEntity *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage;
	Vector		vecSpot;

	Vector vecMid = (vecStart + vecEnd) * 0.5;

//	float searchRadius = (vecStart - vecMid).Length();
	float searchRadius = GARG_FLAME_LENGTH;
	float maxDamageRadius = searchRadius / 2.0;

	Vector vecAim = (vecEnd - vecStart);

	VectorNormalize( vecAim );

	// iterate on all entities in the vicinity.
	while ((pEntity = gEntList.FindEntityInSphere( pEntity, GetAbsOrigin(), searchRadius )) != NULL)
	{

		if ( pEntity->m_takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}
			
			vecSpot = pEntity->BodyTarget( vecMid );
		
			float dist = DotProduct( vecAim, vecSpot - vecMid );
			if (dist > searchRadius)
				dist = searchRadius;
			else if (dist < -searchRadius)
				dist = searchRadius;
			
			Vector vecSrc = vecMid + dist * vecAim;

			UTIL_TraceLine ( vecStart, vecSpot, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
//			NDebugOverlay::Line( vecStart, vecSpot, 0, 255, 0, false, 10.0f );

			if ( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
			{// the explosion can 'see' this entity, so hurt them!
				// decrease damage for an ent that's farther from the flame.
				dist = ( vecSrc - tr.endpos ).Length();

				if (dist > maxDamageRadius)
				{
					flAdjustedDamage = flDamage - (dist - maxDamageRadius) * 0.4;
					if (flAdjustedDamage <= 0)
						continue;
				}
				else
				{
					flAdjustedDamage = flDamage;
				}

				// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
				if (tr.fraction != 1.0)
				{
					ClearMultiDamage( );

					Vector vDir = (tr.endpos - vecSrc);
					VectorNormalize( vDir );

					CTakeDamageInfo info( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
					CalculateMeleeDamageForce( &info, vDir, tr.endpos );
					pEntity->DispatchTraceAttack( info, vDir, &tr );
					ApplyMultiDamage();
				}
				else
				{
					pEntity->TakeDamage( CTakeDamageInfo( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType ) );
				}
			}
		}
	}
}


void CNPC_Gargantua::FlameDestroy( void )
{
	int i;

	CPASAttenuationFilter filter4( this );
	enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, pBeamAttackSounds[ 0 ], 1, ATTN_NORM, 0, PITCH_NORM );
	
	for ( i = 0; i < 4; i++ )
	{
		if ( m_pFlame[i] )
		{
			UTIL_Remove( m_pFlame[i] );
			m_pFlame[i] = NULL;
		}
	}
}


void CNPC_Gargantua::EyeOn( int level )
{
	m_eyeBrightness = level;	
}

void CNPC_Gargantua::EyeOff( void )
{
	m_eyeBrightness = 0;
}

void CNPC_Gargantua::EyeUpdate( void )
{
	if ( m_pEyeGlow )
	{
		m_pEyeGlow->SetBrightness( UTIL_Approach( m_eyeBrightness, m_pEyeGlow->GetBrightness(), 26 ), 0.5f );
		if ( m_pEyeGlow->GetBrightness() == 0 )
		{
			m_pEyeGlow->m_fEffects |= EF_NODRAW;
		}
		else
		{
			m_pEyeGlow->m_fEffects &= ~EF_NODRAW;
		}
	}
}


void CNPC_Gargantua::StompAttack( void )
{
	trace_t trace;

	Vector vecForward;
	AngleVectors(GetAbsAngles(), &vecForward );
	Vector vecStart = GetAbsOrigin() + Vector(0,0,60) + 35 * vecForward;

	CBaseEntity* pPlayer = GetEnemy();
	if ( !pPlayer )
		return;

	Vector vecAim = pPlayer->GetAbsOrigin() - GetAbsOrigin();
	VectorNormalize( vecAim );
	Vector vecEnd = (vecAim * 1024) + vecStart;

	UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
//	NDebugOverlay::Line( vecStart, vecEnd, 255, 0, 0, false, 10.0f );

	CStomp::StompCreate( vecStart, trace.endpos, 0, this );
	UTIL_ScreenShake( GetAbsOrigin(), 12.0, 100.0, 2.0, 1000, SHAKE_START );
	CPASAttenuationFilter filter( this );
	enginesound->EmitSound( filter, entindex(), CHAN_VOICE, pStompSounds[ RandomInt(0,ARRAYSIZE(pStompSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + RandomInt(-10,10) );

	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,20), MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
	if ( trace.fraction < 1.0 )
	{
		UTIL_DecalTrace( &trace, "SmallScorch" );
	}
}

void CNPC_Gargantua::DeathEffect( void )
{
	int i;

	Vector vForward;
	AngleVectors( GetAbsAngles(), &vForward );
	Vector deathPos = GetAbsOrigin() + vForward * 100;

	Vector position = GetAbsOrigin();
	position.z += 32;

	CPASFilter filter( GetAbsOrigin() );
	for ( 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_Smoke(GetAbsOrigin(),random->RandomInt(10, 15), 10);
	UTIL_ScreenShake( GetAbsOrigin(), 25.0, 100.0, 5.0, 1000, SHAKE_START );

}

void CNPC_Gargantua::Event_Killed( const CTakeDamageInfo &info )
{
	EyeOff();
	UTIL_Remove( m_pEyeGlow );
	m_pEyeGlow = NULL;
	BaseClass::Event_Killed( info );
}

void CNPC_Gargantua::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
{
	CTakeDamageInfo subInfo = info;

	if ( !IsAlive() )
	{
		BaseClass::TraceAttack( subInfo, vecDir, ptr );
		return;
	}

	// UNDONE: Hit group specific damage?
	if ( subInfo.GetDamageType() & ( GARG_DAMAGE | DMG_BLAST ) )
	{
		if ( m_painSoundTime < gpGlobals->curtime )
		{
			CPASAttenuationFilter filter( this );
			EmitSound( filter, entindex(), CHAN_VOICE, pPainSounds[ random->RandomInt(0,ARRAYSIZE(pPainSounds)-1) ], 1, ATTN_GARG );

			m_painSoundTime = gpGlobals->curtime + random->RandomFloat( 2.5, 4 );
		}
	}

	int bitsDamageType = subInfo.GetDamageType();

	bitsDamageType &= GARG_DAMAGE;

	subInfo.SetDamageType( bitsDamageType );

	if ( subInfo.GetDamageType() == 0 )
	{
		if ( m_flDmgTime != gpGlobals->curtime || (random->RandomInt( 0, 100 ) < 20) )
		{
			g_pEffects->Ricochet(ptr->endpos, -vecDir );
			m_flDmgTime = gpGlobals->curtime;
		}

		subInfo.SetDamage( 0 );
	}

	BaseClass::TraceAttack( subInfo, vecDir, ptr );
}

int CNPC_Gargantua::OnTakeDamage_Alive( const CTakeDamageInfo &info )
{
	CTakeDamageInfo subInfo = info;

	float flDamage = subInfo.GetDamage();

	if ( IsAlive() )
	{
		if ( !(subInfo.GetDamageType() & GARG_DAMAGE) )
		{
			 flDamage *= 0.01;
			 subInfo.SetDamage( flDamage );
		}
		if ( subInfo.GetDamageType() & DMG_BLAST )
		{
			SetCondition( COND_LIGHT_DAMAGE );
		}
	}

	return BaseClass::OnTakeDamage_Alive( subInfo );
}

AI_BEGIN_CUSTOM_NPC( monster_gargantua, CNPC_Gargantua )

DECLARE_TASK ( TASK_SOUND_ATTACK )
DECLARE_TASK ( TASK_FLAME_SWEEP )

	//=========================================================
	// > SCHED_GARG_FLAME
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_GARG_FLAME,

		"	Tasks"
		"		TASK_STOP_MOVING			0"
		"		TASK_FACE_ENEMY				0"
		"		TASK_SOUND_ATTACK			0"
		"		TASK_SET_ACTIVITY			ACTIVITY:ACT_MELEE_ATTACK2"
		"		TASK_FLAME_SWEEP			4.5"
		"		TASK_SET_ACTIVITY			ACTIVITY:ACT_IDLE"
	)

	//=========================================================
	// > SCHED_GARG_SWIPE
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_GARG_SWIPE,

		"	Tasks"
		"		TASK_STOP_MOVING			0"
		"		TASK_FACE_ENEMY				0"
		"		TASK_MELEE_ATTACK1			0"
		"	"
		"	Interrupts"
		"   COND_CAN_MELEE_ATTACK2"
	)

AI_END_CUSTOM_NPC()

⌨️ 快捷键说明

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