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

📄 hl1_npc_controller.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	for (int i = 0; i < 2; i++)
	{
		if (m_pBall[i] == NULL)
		{
			m_pBall[i] = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), TRUE );
			m_pBall[i]->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
			m_pBall[i]->SetAttachment( this, (i + 3) );
			m_pBall[i]->SetScale( 1.0 );
		}

		float t = m_iBallTime[i] - gpGlobals->curtime;
		if (t > 0.1)
			t = 0.1 / t;
		else
			t = 1.0;

		m_iBallCurrent[i] += (m_iBall[i] - m_iBallCurrent[i]) * t;

		m_pBall[i]->SetBrightness( m_iBallCurrent[i] );

		GetAttachment( i + 2, vecStart, angleGun );
		m_pBall[i]->SetAbsOrigin( vecStart );

		CBroadcastRecipientFilter filter;
		GetAttachment( i + 3, vecStart, angleGun );
		te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0/*exponent*/, m_iBallCurrent[i] / 8 /*radius*/, 0.5, 0 );
	}
}

//=========================================================
// Stop  - 
//=========================================================
void CNPC_Controller::Stop( void ) 
{ 
	SetIdealActivity( GetStoppedActivity() );
}

//-----------------------------------------------------------------------------
// Purpose: Handles movement towards the last move target.
// Input  : flInterval - 
//-----------------------------------------------------------------------------
bool CNPC_Controller::OverridePathMove( float flInterval )
{
	CBaseEntity *pMoveTarget = (GetTarget()) ? GetTarget() : GetEnemy();
	Vector waypointDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();

	float flWaypointDist = waypointDir.Length2D();
	VectorNormalize(waypointDir);

	// cut corner?
	if (flWaypointDist < 128)
	{
		if (m_flGroundSpeed > 100)
			m_flGroundSpeed -= 40;
	}
	else
	{
		if (m_flGroundSpeed < 400)
			m_flGroundSpeed += 10;
	}

	m_velocity = m_velocity * 0.8 + m_flGroundSpeed * waypointDir * 0.5;
	SetAbsVelocity( m_velocity );

	// -----------------------------------------------------------------
	// Check route is blocked
	// ------------------------------------------------------------------
	Vector checkPos = GetLocalOrigin() + (waypointDir * (m_flGroundSpeed * flInterval));

	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_FLY, GetLocalOrigin(), checkPos, MASK_NPCSOLID|CONTENTS_WATER,
		pMoveTarget, &moveTrace);
	if (IsMoveBlocked( moveTrace ))
	{
		TaskFail(FAIL_NO_ROUTE);
		GetNavigator()->ClearGoal();
		return true;
	}

	// ----------------------------------------------
	
	Vector lastPatrolDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();
	
	if ( ProgressFlyPath( flInterval, pMoveTarget, MASK_NPCSOLID, false, 64 ) == AINPP_COMPLETE )
	{
		{
			m_vLastPatrolDir = lastPatrolDir;
			VectorNormalize(m_vLastPatrolDir);
		}
		return true;
	}
	return false;
}

bool CNPC_Controller::OverrideMove( float flInterval )
{
	if (m_flGroundSpeed == 0)
	{
		m_flGroundSpeed = 100;
	}

	// ----------------------------------------------
	//	Select move target 
	// ----------------------------------------------
	CBaseEntity *pMoveTarget = NULL;
	if (GetTarget() != NULL )
	{
		pMoveTarget = GetTarget();
	}
	else if (GetEnemy() != NULL )
	{
		pMoveTarget		= GetEnemy();
	}

	// ----------------------------------------------
	//	Select move target position 
	// ----------------------------------------------
	Vector vMoveTargetPos(0,0,0);
	if (GetTarget())
	{
		vMoveTargetPos = GetTarget()->GetAbsOrigin();
	}
	else if (GetEnemy() != NULL)
	{
		vMoveTargetPos = GetEnemy()->GetAbsOrigin();
	}

	// -----------------------------------------
	//  See if we can fly there directly
	// -----------------------------------------
	if (pMoveTarget /*|| HaveInspectTarget()*/)
	{
		trace_t tr;

		if (pMoveTarget)
		{
			UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, 
				MASK_NPCSOLID_BRUSHONLY, pMoveTarget, GetCollisionGroup(), &tr);
		}
		else
		{
			UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, &tr);
		}
/*
		float fTargetDist = (1-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length();
		if (fTargetDist > 50)
		{
			//SetCondition( COND_SCANNER_FLY_BLOCKED );
		}
		else
		{
			//SetCondition( COND_SCANNER_FLY_CLEAR );
		}
*/
	}

	// -----------------------------------------------------------------
	// If I have a route, keep it updated and move toward target
	// ------------------------------------------------------------------
	if (GetNavigator()->IsGoalActive())
	{
		if ( OverridePathMove( flInterval ) )
			return true;
	}
	else
	{
		//do nothing
		Stop();
		TaskComplete();
	}

	return true;
}

void CNPC_Controller::MoveToTarget( float flInterval, const Vector &vecMoveTarget )
{
	const float	myAccel	 = 300.0;
	const float	myDecay	 = 9.0;
	
	//TurnHeadToTarget( flInterval, MoveTarget );
	MoveToLocation( flInterval, vecMoveTarget, myAccel, (2 * myAccel), myDecay );
}

//=========================================================
// Controller bouncy ball attack
//=========================================================

LINK_ENTITY_TO_CLASS( controller_head_ball, CNPC_ControllerHeadBall );

BEGIN_DATADESC( CNPC_ControllerHeadBall )

	DEFINE_THINKFUNC( CNPC_ControllerHeadBall, HuntThink ),
	DEFINE_THINKFUNC( CNPC_ControllerHeadBall, KillThink ),
	DEFINE_ENTITYFUNC( CNPC_ControllerHeadBall, BounceTouch ),

END_DATADESC()


void CNPC_ControllerHeadBall::Spawn( void )
{
	Precache( );
	// motor
	SetMoveType( MOVETYPE_FLY );
	SetSolid( SOLID_BBOX );
	SetSize( vec3_origin, vec3_origin );

	m_pSprite = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), FALSE );
	m_pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
	m_pSprite->SetAttachment( this, 0 );
	m_pSprite->SetScale( 2.0 );

	UTIL_SetSize( this, Vector( 0, 0, 0), Vector(0, 0, 0) );
	UTIL_SetOrigin( this, GetAbsOrigin() );

	SetThink( &CNPC_ControllerHeadBall::HuntThink );
	SetTouch( &CNPC_ControllerHeadBall::BounceTouch );

//	m_vecIdeal = vec3_origin;	//(0,0,0)

	SetNextThink( gpGlobals->curtime + 0.1 );

	m_hOwner = GetOwnerEntity();

	m_flSpawnTime = gpGlobals->curtime;
}


void CNPC_ControllerHeadBall :: Precache( void )
{
	engine->PrecacheModel( "sprites/xspark4.vmt");
	enginesound->PrecacheSound("debris/zap4.wav");
	enginesound->PrecacheSound("weapons/electro4.wav");
}

extern short		g_sModelIndexLaser;	

void CNPC_ControllerHeadBall :: HuntThink( void  )
{
	SetNextThink( gpGlobals->curtime + 0.1 );

	m_pSprite->SetBrightness( m_pSprite->GetBrightness() - 5, 0.1f );

	CBroadcastRecipientFilter filter;
	te->DynamicLight( filter, 0.0, &GetAbsOrigin(), 255, 255, 255, 0, m_pSprite->GetBrightness() / 16, 0.2, 0 );

	// check world boundaries
	if (gpGlobals->curtime - m_flSpawnTime > 5 || m_pSprite->GetBrightness() < 64 /*|| GetEnemy() == NULL || m_hOwner == NULL*/ || !IsInWorld() )
	{
		SetTouch( NULL );
		SetThink( KillThink );
		SetNextThink( gpGlobals->curtime );
		return;
	}

	if( !GetEnemy() )
		return;

	MovetoTarget( GetEnemy()->GetAbsOrigin() );

	if ((GetEnemy()->WorldSpaceCenter() - GetAbsOrigin()).Length() < 64)
	{
		trace_t tr;

		UTIL_TraceLine( GetAbsOrigin(), GetEnemy()->WorldSpaceCenter(), MASK_ALL, this, COLLISION_GROUP_NONE, &tr );

		CBaseEntity *pEntity = tr.m_pEnt;
		if (pEntity != NULL && pEntity->m_takedamage == DAMAGE_YES)
		{
			ClearMultiDamage( );
			Vector dir = GetAbsVelocity();
			VectorNormalize( dir );
			CTakeDamageInfo info( this, this, sk_controller_dmgball.GetFloat(), DMG_SHOCK );
			CalculateMeleeDamageForce( &info, dir, tr.endpos );
			pEntity->DispatchTraceAttack( info, dir, &tr );
			ApplyMultiDamage();

			int haloindex = 0;
			int fadelength = 0;
			int amplitude = 0;
			const Vector vecEnd = tr.endpos;
			te->BeamEntPoint( filter, 0.0, entindex(), NULL, 0, &(tr.m_pEnt->GetAbsOrigin()), 
				g_sModelIndexLaser, haloindex /* no halo */, 0, 10, 3, 20, 20, fadelength, 
				amplitude, 255, 255, 255, 255, 10 );

		}

		UTIL_EmitAmbientSound( this, GetAbsOrigin(), "weapons/electro4.wav", 0.5, SNDLVL_NORM, 0, 100 );

		SetNextAttack( gpGlobals->curtime + 3.0 );

		SetThink( KillThink );
		SetNextThink( gpGlobals->curtime + 0.3 );
	}
}

void CNPC_ControllerHeadBall::MovetoTarget( Vector vecTarget )
{
	// accelerate
	float flSpeed = m_vecIdeal.Length();
	if (flSpeed == 0)
	{
		m_vecIdeal = GetAbsVelocity();
		flSpeed = m_vecIdeal.Length();
	}

	if (flSpeed > 400)
	{
		VectorNormalize( m_vecIdeal );
		m_vecIdeal = m_vecIdeal * 400;
	}

	Vector t = vecTarget - GetAbsOrigin();
	VectorNormalize(t);
	m_vecIdeal = m_vecIdeal + t * 100;
	SetAbsVelocity(m_vecIdeal);
}

void CNPC_ControllerHeadBall::BounceTouch( CBaseEntity *pOther )
{
	Vector vecDir = m_vecIdeal;
	VectorNormalize( vecDir );

	trace_t tr = CBaseEntity::GetTouchTrace( );

	float n = -DotProduct(tr.plane.normal, vecDir);

	vecDir = 2.0 * tr.plane.normal * n + vecDir;

	m_vecIdeal = vecDir * m_vecIdeal.Length();
}

void CNPC_ControllerHeadBall::KillThink( void )
{
	UTIL_Remove( m_pSprite );
	UTIL_Remove( this );
}


//=========================================================
// Controller Zap attack
//=========================================================

LINK_ENTITY_TO_CLASS( controller_energy_ball, CNPC_ControllerZapBall );

BEGIN_DATADESC( CNPC_ControllerZapBall )

	DEFINE_THINKFUNC( CNPC_ControllerZapBall, AnimateThink ),
	DEFINE_ENTITYFUNC( CNPC_ControllerZapBall, ExplodeTouch ),

END_DATADESC()


void CNPC_ControllerZapBall::Spawn( void )
{
	Precache( );
	// motor
	SetMoveType( MOVETYPE_FLY );
//	SetSolid( SOLID_CUSTOM );
	SetSolid( SOLID_BBOX );
	SetSize( vec3_origin, vec3_origin );

	m_pSprite = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), FALSE );
	m_pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
	m_pSprite->SetAttachment( this, 0 );
	m_pSprite->SetScale( 0.5 );

	UTIL_SetSize( this, Vector( 0, 0, 0), Vector(0, 0, 0) );
	UTIL_SetOrigin( this, GetAbsOrigin() );

	SetThink( &CNPC_ControllerZapBall::AnimateThink );
	SetTouch( &CNPC_ControllerZapBall::ExplodeTouch );

	m_hOwner = GetOwnerEntity();

	m_flSpawnTime = gpGlobals->curtime; // keep track of when ball spawned
	SetNextThink( gpGlobals->curtime + 0.1 );
}


void CNPC_ControllerZapBall :: Precache( void )
{
	engine->PrecacheModel( "sprites/xspark4.vmt");
}


void CNPC_ControllerZapBall::AnimateThink( void  )
{
	SetNextThink( gpGlobals->curtime + 0.1 );
	
	m_flCycle = ((int)m_flCycle + 1) % 11;

	if (gpGlobals->curtime - m_flSpawnTime > 5 || GetAbsVelocity().Length() < 10)
	{
		SetTouch( NULL );
		Kill();
	}
}


void CNPC_ControllerZapBall::ExplodeTouch( CBaseEntity *pOther )
{
	if (m_takedamage = DAMAGE_YES )
	{
		trace_t	tr = GetTouchTrace( );

		ClearMultiDamage( );

		Vector vecAttackDir = GetAbsVelocity();
		VectorNormalize( vecAttackDir );

		if (m_hOwner != NULL)
		{
			CTakeDamageInfo info( this, m_hOwner, sk_controller_dmgball.GetFloat(), DMG_ENERGYBEAM );
			CalculateMeleeDamageForce( &info, vecAttackDir, tr.endpos );
			pOther->DispatchTraceAttack( info, vecAttackDir, &tr );
		}
		else
		{
			CTakeDamageInfo info( this, this, sk_controller_dmgball.GetFloat(), DMG_ENERGYBEAM );
			CalculateMeleeDamageForce( &info, vecAttackDir, tr.endpos );
			pOther->DispatchTraceAttack( info, vecAttackDir, &tr );
		}

		ApplyMultiDamage();

	//	void UTIL_EmitAmbientSound( CBaseEntity *entity, const Vector &vecOrigin, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float soundtime /*= 0.0f*/ )

		UTIL_EmitAmbientSound( this, tr.endpos, "weapons/electro4.wav", 0.3, SNDLVL_NORM, 0, random->RandomInt( 90, 99 ) );
	}

	Kill();
}

void CNPC_ControllerZapBall::Kill( void )
{
	UTIL_Remove( m_pSprite );
	UTIL_Remove( this );
}

⌨️ 快捷键说明

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