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

📄 hl1_npc_barnacle.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:		barnacle - stationary ceiling mounted 'fishing' monster	
//
// $Workfile:     $
// $Date:         $
// $NoKeywords: $
//=============================================================================

#include "cbase.h"
#include "hl1_npc_barnacle.h"
#include "NPCEvent.h"
#include "gib.h"
#include "AI_Default.h"
#include "activitylist.h"
#include "hl2_player.h"
#include "vstdlib/random.h"
#include "physics_saverestore.h"
#include "vcollide_parse.h"
#include "engine/IEngineSound.h"

ConVar	sk_barnacle_health( "sk_barnacle_health","0");

//-----------------------------------------------------------------------------
// Private activities.
//-----------------------------------------------------------------------------
static int ACT_EAT = 0;

//-----------------------------------------------------------------------------
// Interactions
//-----------------------------------------------------------------------------
int	g_interactionBarnacleVictimDangle	= 0;
int	g_interactionBarnacleVictimReleased	= 0;
int	g_interactionBarnacleVictimGrab		= 0;

LINK_ENTITY_TO_CLASS( monster_barnacle, CNPC_Barnacle );
IMPLEMENT_CUSTOM_AI( monster_barnacle, CNPC_Barnacle );

//-----------------------------------------------------------------------------
// Purpose: Initialize the custom schedules
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_Barnacle::InitCustomSchedules(void) 
{
	INIT_CUSTOM_AI(CNPC_Barnacle);

	ADD_CUSTOM_ACTIVITY(CNPC_Barnacle, ACT_EAT);

	g_interactionBarnacleVictimDangle	= CBaseCombatCharacter::GetInteractionID();
	g_interactionBarnacleVictimReleased	= CBaseCombatCharacter::GetInteractionID();
	g_interactionBarnacleVictimGrab		= CBaseCombatCharacter::GetInteractionID();	
}


BEGIN_DATADESC( CNPC_Barnacle )

	DEFINE_FIELD( CNPC_Barnacle, m_flAltitude, FIELD_FLOAT ),
	DEFINE_FIELD( CNPC_Barnacle, m_flKillVictimTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_Barnacle, m_cGibs, FIELD_INTEGER ),// barnacle loads up on gibs each time it kills something.
	DEFINE_FIELD( CNPC_Barnacle, m_fTongueExtended, FIELD_BOOLEAN ),
	DEFINE_FIELD( CNPC_Barnacle, m_fLiftingPrey, FIELD_BOOLEAN ),
	DEFINE_FIELD( CNPC_Barnacle, m_flTongueAdj, FIELD_FLOAT ),

	// Function pointers
	DEFINE_THINKFUNC( CNPC_Barnacle, BarnacleThink ),
	DEFINE_THINKFUNC( CNPC_Barnacle, WaitTillDead ),
END_DATADESC()


//=========================================================
// Classify - indicates this monster's place in the 
// relationship table.
//=========================================================
Class_T	CNPC_Barnacle::Classify ( void )
{
	return	CLASS_ALIEN_MONSTER;
}

//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CNPC_Barnacle::HandleAnimEvent( animevent_t *pEvent )
{
	switch( pEvent->event )
	{
	case BARNACLE_AE_PUKEGIB:
		CGib::SpawnRandomGibs( this, 1, GIB_HUMAN );	
		break;
	default:
		BaseClass::HandleAnimEvent( pEvent );
		break;
	}
}

//=========================================================
// Spawn
//=========================================================
void CNPC_Barnacle::Spawn()
{
	Precache( );

	SetModel( "models/barnacle.mdl" );
	UTIL_SetSize( this, Vector(-16, -16, -32), Vector(16, 16, 0) );

	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_NOT_STANDABLE );
	SetMoveType( MOVETYPE_NONE );
	SetBloodColor( BLOOD_COLOR_GREEN );
	m_iHealth			= sk_barnacle_health.GetFloat();
	m_flFieldOfView		= 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
	m_NPCState			= NPC_STATE_NONE;
	m_flKillVictimTime	= 0;
	m_cGibs				= 0;
	m_fLiftingPrey		= FALSE;
	m_takedamage		= DAMAGE_YES;

	InitBoneControllers();
	InitTonguePosition();

	// set eye position
	SetDefaultEyeOffset();

	SetActivity ( ACT_IDLE );

	SetThink ( BarnacleThink );
	SetNextThink( gpGlobals->curtime + 0.5f );

	Relink();

	//Do not have a shadow
	m_fEffects |= EF_NOSHADOW;
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
int	CNPC_Barnacle::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
{
	CTakeDamageInfo info = inputInfo;
	if ( info.GetDamageType() & DMG_CLUB )
	{
		info.SetDamage( m_iHealth );
	}

	return BaseClass::OnTakeDamage_Alive( info );
}

//-----------------------------------------------------------------------------
// Purpose: Initialize tongue position when first spawned
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_Barnacle::InitTonguePosition( void )
{
	CBaseEntity *pTouchEnt;
	float flLength;

	pTouchEnt = TongueTouchEnt( &flLength );
	m_flAltitude = flLength;

	Vector origin;
	QAngle angle;

	GetAttachment( "TongueEnd", origin, angle );

	m_flTongueAdj = origin.z - GetAbsOrigin().z;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_Barnacle::BarnacleThink ( void )
{
	CBaseEntity *pTouchEnt;
	float flLength;

	SetNextThink( gpGlobals->curtime + 0.1f );

	if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
	{
		// AI Disabled, don't do anything
	}
	else if ( GetEnemy() != NULL )
	{
// barnacle has prey.

		if ( !GetEnemy()->IsAlive() )
		{
			// someone (maybe even the barnacle) killed the prey. Reset barnacle.
			m_fLiftingPrey = FALSE;// indicate that we're not lifting prey.
			SetEnemy( NULL );
			return;
		}

		CBaseCombatCharacter* pVictim = GetEnemyCombatCharacterPointer();
		Assert( pVictim );

		if ( m_fLiftingPrey )
		{	

			if ( GetEnemy() != NULL && pVictim->m_lifeState == LIFE_DEAD )
			{
				// crap, someone killed the prey on the way up.
				SetEnemy( NULL );
				m_fLiftingPrey = FALSE;
				return;
			}

	// still pulling prey.
			Vector vecNewEnemyOrigin = GetEnemy()->GetLocalOrigin();
			vecNewEnemyOrigin.x = GetLocalOrigin().x;
			vecNewEnemyOrigin.y = GetLocalOrigin().y;

			// guess as to where their neck is
			// FIXME: remove, ask victim where their neck is
			vecNewEnemyOrigin.x -= 6 * cos(GetEnemy()->GetLocalAngles().y * M_PI/180.0);	
			vecNewEnemyOrigin.y -= 6 * sin(GetEnemy()->GetLocalAngles().y * M_PI/180.0);

			m_flAltitude -= BARNACLE_PULL_SPEED;
			vecNewEnemyOrigin.z += BARNACLE_PULL_SPEED;

			if ( fabs( GetLocalOrigin().z - ( vecNewEnemyOrigin.z + GetEnemy()->GetViewOffset().z - 12 ) ) < BARNACLE_BODY_HEIGHT )
			{
		// prey has just been lifted into position ( if the victim origin + eye height + 8 is higher than the bottom of the barnacle, it is assumed that the head is within barnacle's body )
				m_fLiftingPrey = FALSE;

				CPASAttenuationFilter filter( this );
				EmitSound( filter, entindex(), CHAN_WEAPON, "barnacle/bcl_bite3.wav", 1, ATTN_NORM );

				// Take a while to kill the player
				m_flKillVictimTime = gpGlobals->curtime + 10;
						
				if ( pVictim )
				{
					pVictim->HandleInteraction( g_interactionBarnacleVictimDangle, NULL, this );
					SetActivity ( (Activity)ACT_EAT );
				}
			}

			UTIL_SetOrigin ( GetEnemy(), vecNewEnemyOrigin );
		}
		else

⌨️ 快捷键说明

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