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

📄 hl1_npc_barnacle.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		{
	// prey is lifted fully into feeding position and is dangling there.

			if ( m_flKillVictimTime != -1 && gpGlobals->curtime > m_flKillVictimTime )
			{
				// kill!
				if ( pVictim )
				{
					// DMG_CRUSH added so no physics force is generated
					pVictim->TakeDamage( CTakeDamageInfo( this, this, pVictim->m_iHealth, DMG_SLASH | DMG_ALWAYSGIB | DMG_CRUSH ) );
					m_cGibs = 3;
				}

				return;
			}

			// bite prey every once in a while
			if ( pVictim && ( random->RandomInt( 0, 49 ) == 0 ) )
			{
				CPASAttenuationFilter filter( this );
				
				
				switch ( random->RandomInt(0,2) )
				{
					case 0:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break;
					case 1:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM );	break;
					case 2:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM );	break;
				}

				if ( pVictim )
				{
					pVictim->HandleInteraction( g_interactionBarnacleVictimDangle, NULL, this );
				}
			}
		}
	}
	else
	{
// barnacle has no prey right now, so just idle and check to see if anything is touching the tongue.

		// If idle and no nearby client, don't think so often
		if ( !UTIL_FindClientInPVS( edict() ) )
			SetNextThink( random->RandomFloat(1,1.5) );	// Stagger a bit to keep barnacles from thinking on the same frame

		if ( IsActivityFinished() )
		{// this is done so barnacle will fidget.
			SetActivity ( ACT_IDLE );
		}

		if ( m_cGibs && random->RandomInt(0,99) == 1 )
		{
			// cough up a gib.
			CGib::SpawnRandomGibs( this, 1, GIB_HUMAN );
			m_cGibs--;

			CPASAttenuationFilter filter( this );

			switch ( random->RandomInt(0,2) )
			{
				case 0:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break;
				case 1:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM );	break;
				case 2:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM );	break;
			}
		}

		pTouchEnt = TongueTouchEnt( &flLength );

		if ( pTouchEnt != NULL && m_fTongueExtended )
		{
			// tongue is fully extended, and is touching someone.
			CBaseCombatCharacter* pBCC = (CBaseCombatCharacter *)pTouchEnt;

			// FIXME: humans should return neck position
			Vector vecGrabPos = pTouchEnt->GetAbsOrigin();

			if ( pBCC && pBCC->HandleInteraction( g_interactionBarnacleVictimGrab, &vecGrabPos, this ) )
			{
				CPASAttenuationFilter filter( this );
				EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_alert2.wav", 1, ATTN_NORM );

				SetSequenceByName ( "attack1" );

				SetEnemy( pTouchEnt );

				pTouchEnt->SetMoveType( MOVETYPE_FLY );
				pTouchEnt->SetAbsVelocity( vec3_origin );
				pTouchEnt->SetBaseVelocity( vec3_origin );
				Vector origin = GetAbsOrigin();
				origin.z = pTouchEnt->GetAbsOrigin().z;
				pTouchEnt->SetLocalOrigin( origin );
				
				m_fLiftingPrey = TRUE;// indicate that we should be lifting prey.
				m_flKillVictimTime = -1;// set this to a bogus time while the victim is lifted.

				m_flAltitude = (GetAbsOrigin().z - vecGrabPos.z);
			}
		}
		else
		{
			// calculate a new length for the tongue to be clear of anything else that moves under it. 
			if ( m_flAltitude < flLength )
			{
				// if tongue is higher than is should be, lower it kind of slowly.
				m_flAltitude += BARNACLE_PULL_SPEED;
				m_fTongueExtended = FALSE;
			}
			else
			{
				m_flAltitude = flLength;
				m_fTongueExtended = TRUE;
			}

		}

	}

	// ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj );
	// NDebugOverlay::Box( GetAbsOrigin() - Vector( 0, 0, m_flAltitude ), Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,255,255, 0, 0.1 );

	//SetBoneController( 0, 0 );//-(m_flAltitude + m_flTongueAdj) );
	SetBoneController( 0, -(m_flAltitude + m_flTongueAdj) );
	StudioFrameAdvance();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_Barnacle::Event_Killed( const CTakeDamageInfo &info )
{
	AddSolidFlags( FSOLID_NOT_SOLID );
	m_takedamage		= DAMAGE_NO;

	Relink();

	if ( GetEnemy() != NULL )
	{
		CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer();

		if ( pVictim )
		{
			pVictim->HandleInteraction( g_interactionBarnacleVictimReleased, NULL, this );
		}
	}

	CGib::SpawnRandomGibs( this, 4, GIB_HUMAN );

	//EmitSound( "NPC_Barnacle.Die" );

	CPASAttenuationFilter filter( this );
				
	switch ( random->RandomInt ( 0, 1 ) )
	{
		case 0:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_die1.wav", 1, ATTN_NORM );	break;
		case 1:	EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_die3.wav", 1, ATTN_NORM );	break;
	}

	SetActivity ( ACT_DIESIMPLE );
	SetBoneController( 0, 0 );

	StudioFrameAdvance();

	SetNextThink( gpGlobals->curtime + 0.1f );
	SetThink ( WaitTillDead );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_Barnacle::WaitTillDead ( void )
{
	SetNextThink( gpGlobals->curtime + 0.1f );

	StudioFrameAdvance();
	DispatchAnimEvents ( this );

	if ( IsActivityFinished() )
	{
		// death anim finished. 
		StopAnimation();
		SetThink ( NULL );
	}
}

//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CNPC_Barnacle::Precache()
{
	engine->PrecacheModel("models/barnacle.mdl");

	enginesound->PrecacheSound("barnacle/bcl_alert2.wav");//happy, lifting food up
	enginesound->PrecacheSound("barnacle/bcl_bite3.wav");//just got food to mouth
	enginesound->PrecacheSound("barnacle/bcl_chew1.wav");
	enginesound->PrecacheSound("barnacle/bcl_chew2.wav");
	enginesound->PrecacheSound("barnacle/bcl_chew3.wav");
	enginesound->PrecacheSound("barnacle/bcl_die1.wav" );
	enginesound->PrecacheSound("barnacle/bcl_die3.wav" );

	BaseClass::Precache();
}	

//=========================================================
// TongueTouchEnt - does a trace along the barnacle's tongue
// to see if any entity is touching it. Also stores the length
// of the trace in the int pointer provided.
//=========================================================
#define BARNACLE_CHECK_SPACING	8
CBaseEntity *CNPC_Barnacle::TongueTouchEnt ( float *pflLength )
{
	trace_t		tr;
	float		length;

	// trace once to hit architecture and see if the tongue needs to change position.
	UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() - Vector ( 0 , 0 , 2048 ), 
		MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
	
	length = fabs( GetAbsOrigin().z - tr.endpos.z );
	// Pull it up a tad
	length -= 16;
	if ( pflLength )
	{
		*pflLength = length;
	}

	Vector delta = Vector( BARNACLE_CHECK_SPACING, BARNACLE_CHECK_SPACING, 0 );
	Vector mins = GetAbsOrigin() - delta;
	Vector maxs = GetAbsOrigin() + delta;
	maxs.z = GetAbsOrigin().z;
	mins.z -= length;

	CBaseEntity *pList[10];
	int count = UTIL_EntitiesInBox( pList, 10, mins, maxs, (FL_CLIENT|FL_NPC) );
	if ( count )
	{
		for ( int i = 0; i < count; i++ )
		{
			CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pList[ i ] );

			bool bCanHurt = false;

			if ( IRelationType( pList[i] ) == D_HT || IRelationType( pList[i] ) == D_FR )
				 bCanHurt = true;

			if ( pList[i] != this && bCanHurt == true && pVictim->m_lifeState == LIFE_ALIVE )
			{
				return pList[i];
			}
		}
	}

	return NULL;
}

⌨️ 快捷键说明

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