📄 hl1_npc_barnacle.cpp
字号:
{
// 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 + -