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

📄 hl1_npc_controller.cpp

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

			CBroadcastRecipientFilter filter;
			te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.2, -32 );
		
			m_iBall[0] = 192;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 255;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;

		}
		break;

		case CONTROLLER_AE_BALL_SHOOT:
		{
			Vector vecStart;
			QAngle angleGun;
			
			GetAttachment( 1, vecStart, angleGun );

			CBroadcastRecipientFilter filter;
			te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.1, 32 );

			CAI_BaseNPC *pBall = (CAI_BaseNPC*)Create( "controller_head_ball", vecStart, angleGun );

			pBall->SetAbsVelocity( Vector(0,0,32) );
			pBall->SetEnemy( GetEnemy() );

//			DevMsg( 1, "controller shooting head ball\n" );

			m_iBall[0] = 0;
			m_iBall[1] = 0;
		}
		break;

		case CONTROLLER_AE_SMALL_SHOOT:
		{
			AttackSound( );
			m_flShootTime = gpGlobals->curtime;
			m_flShootEnd = m_flShootTime + atoi( pEvent->options ) / 15.0;
		}
		break;
		case CONTROLLER_AE_POWERUP_FULL:
		{
			m_iBall[0] = 255;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 255;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
		}
		break;
		case CONTROLLER_AE_POWERUP_HALF:
		{
			m_iBall[0] = 192;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 192;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
		}
		break;
		default:
			BaseClass::HandleAnimEvent( pEvent );
			break;
	}
}


//=========================================================
// AI Schedules Specific to this monster
//=========================================================

AI_BEGIN_CUSTOM_NPC( monster_alien_controller, CNPC_Controller )

	//declare our tasks
	DECLARE_TASK( TASK_CONTROLLER_CHASE_ENEMY )
	DECLARE_TASK( TASK_CONTROLLER_STRAFE )
	DECLARE_TASK( TASK_CONTROLLER_TAKECOVER )
	DECLARE_TASK( TASK_CONTROLLER_FAIL )

	//=========================================================
	// > SCHED_CONTROLLER_CHASE_ENEMY
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_CONTROLLER_CHASE_ENEMY,

		"	Tasks"
		"		TASK_GET_PATH_TO_ENEMY			128"
		"		TASK_WAIT_FOR_MOVEMENT				0"
		"	"
		"	Interrupts"
		"		COND_NEW_ENEMY"
		"		COND_TASK_FAILED"


	)

	//=========================================================
	// > SCHED_CONTROLLER_STRAFE
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_CONTROLLER_STRAFE,

		"	Tasks"
		"		TASK_WAIT						0.2"
		"		TASK_GET_PATH_TO_ENEMY			128"
		"		TASK_WAIT_FOR_MOVEMENT			  0"
		"		TASK_WAIT						  1"
		"	"
		"	Interrupts"
		"		COND_NEW_ENEMY"
	)

	//=========================================================
	// > SCHED_CONTROLLER_TAKECOVER
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_CONTROLLER_TAKECOVER,

		"	Tasks"
		"		TASK_WAIT						0.2"
		"		TASK_FIND_COVER_FROM_ENEMY		  0"
		"		TASK_WAIT_FOR_MOVEMENT			  0"
		"		TASK_WAIT						  1"
		"	"
		"	Interrupts"
		"		COND_NEW_ENEMY"
	)

	//=========================================================
	// > SCHED_CONTROLLER_FAIL
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_CONTROLLER_FAIL,

		"	Tasks"
		"		TASK_STOP_MOVING					0"
		"		TASK_SET_ACTIVITY					ACTIVITY:ACT_IDLE"
		"		TASK_WAIT							2"
		"		TASK_WAIT_PVS						0"
	)

AI_END_CUSTOM_NPC()

//=========================================================
// StartTask
//=========================================================
void CNPC_Controller::StartTask( const Task_t *pTask )
{
	BaseClass::StartTask( pTask );
}

Vector Intersect( Vector vecSrc, Vector vecDst, Vector vecMove, float flSpeed )
{
	Vector vecTo = vecDst - vecSrc;

	float a = DotProduct( vecMove, vecMove ) - flSpeed * flSpeed;
	float b = 0 * DotProduct(vecTo, vecMove); // why does this work?
	float c = DotProduct( vecTo, vecTo );

	float t;
	if (a == 0)
	{
		t = c / (flSpeed * flSpeed);
	}
	else
	{
		t = b * b - 4 * a * c;
		t = sqrt( t ) / (2.0 * a);
		float t1 = -b +t;
		float t2 = -b -t;

		if (t1 < 0 || t2 < t1)
			t = t2;
		else
			t = t1;
	}

	if (t < 0.1)
		t = 0.1;
	if (t > 10.0)
		t = 10.0;

	Vector vecHit = vecTo + vecMove * t;
	VectorNormalize( vecHit );
	return vecHit * flSpeed;
}


int CNPC_Controller::LookupFloat( )
{
	if (m_velocity.Length( ) < 32.0)
	{
		return LookupSequence( "up" );
	}

	Vector vecForward, vecRight, vecUp;
	AngleVectors( GetAbsAngles(), &vecForward, &vecRight, &vecUp );

	float x = DotProduct( vecForward, m_velocity );
	float y = DotProduct( vecRight, m_velocity );
	float z = DotProduct( vecUp, m_velocity );

	if (fabs(x) > fabs(y) && fabs(x) > fabs(z))
	{
		if (x > 0)
			return LookupSequence( "forward");
		else
			return LookupSequence( "backward");
	}
	else if (fabs(y) > fabs(z))
	{
		if (y > 0)
			return LookupSequence( "right");
		else
			return LookupSequence( "left");
	}
	else
	{
		if (z > 0)
			return LookupSequence( "up");
		else
			return LookupSequence( "down");
	}
}


//=========================================================
// RunTask 
//=========================================================
void CNPC_Controller::RunTask ( const Task_t *pTask )
{
	if (m_flShootEnd > gpGlobals->curtime)
	{
		Vector vecHand;
		QAngle vecAngle;
		
		GetAttachment( 2, vecHand, vecAngle );
	
		while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->curtime)
		{
			Vector vecSrc = vecHand + GetAbsVelocity() * (m_flShootTime - gpGlobals->curtime);
			Vector vecDir;
			
			if (GetEnemy() != NULL)
			{
				if (HasCondition( COND_SEE_ENEMY ))
				{
					m_vecEstVelocity = m_vecEstVelocity * 0.5 + GetEnemy()->GetAbsVelocity() * 0.5;
				}
				else
				{
					m_vecEstVelocity = m_vecEstVelocity * 0.8;
				}
				vecDir = Intersect( vecSrc, GetEnemy()->BodyTarget( GetAbsOrigin() ), m_vecEstVelocity, sk_controller_speedball.GetFloat() );
			
				float delta = 0.03490; // +-2 degree
				vecDir = vecDir + Vector( random->RandomFloat( -delta, delta ), random->RandomFloat( -delta, delta ), random->RandomFloat( -delta, delta ) ) * sk_controller_speedball.GetFloat();

				vecSrc = vecSrc + vecDir * (gpGlobals->curtime - m_flShootTime);
				CAI_BaseNPC *pBall = (CAI_BaseNPC*)Create( "controller_energy_ball", vecSrc, GetAbsAngles(), this );
				pBall->SetAbsVelocity( vecDir );

//				DevMsg( 2, "controller shooting energy ball\n" );
			}
			
			m_flShootTime += 0.2;
		}

		if (m_flShootTime > m_flShootEnd)
		{
			m_iBall[0] = 64;
			m_iBallTime[0] = m_flShootEnd;
			m_iBall[1] = 64;
			m_iBallTime[1] = m_flShootEnd;
			m_fInCombat = FALSE;
		}
	}

	switch ( pTask->iTask )
	{
	case TASK_WAIT_FOR_MOVEMENT:
	case TASK_WAIT:
	case TASK_WAIT_FACE_ENEMY:
	case TASK_WAIT_PVS:
		{
			if( GetEnemy() )
			{
				float idealYaw = UTIL_VecToYaw( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() );
				GetMotor()->SetIdealYawAndUpdate( idealYaw );
			}

			if ( IsSequenceFinished() || GetActivity() == ACT_IDLE)
			{
				m_fInCombat = false;
			}

			BaseClass::RunTask ( pTask );

			if (!m_fInCombat)
			{
				if( HasCondition( COND_CAN_RANGE_ATTACK1 ))
				{
					SetActivity( ACT_RANGE_ATTACK1 );
					m_flCycle = 0;
					ResetSequenceInfo( );
					m_fInCombat = true;
				}
				else if( HasCondition( COND_CAN_RANGE_ATTACK2 ) )
				{
					SetActivity( ACT_RANGE_ATTACK2 );
					m_flCycle = 0;
					ResetSequenceInfo( );
					m_fInCombat = true;
				}
				else
				{
					int iFloat = LookupFloat();
					if( IsSequenceFinished() || iFloat != GetSequence() )
					{
						SetSequence( iFloat );
						m_flCycle = 0;
						ResetSequenceInfo( );
					}
				}
			}
		}
		break;
	default: 
		BaseClass::RunTask ( pTask );
		break;
	}
}

void CNPC_Controller::SetSequence( int nSequence )
{
	int x;

	x = 4;

	BaseClass::SetSequence( nSequence );
}


//=========================================================
//=========================================================
int CNPC_Controller::TranslateSchedule( int scheduleType )
{
	switch	( scheduleType )
	{
	case SCHED_CHASE_ENEMY:
		return SCHED_CONTROLLER_CHASE_ENEMY;
	case SCHED_RANGE_ATTACK1:
		return SCHED_CONTROLLER_STRAFE;
	case SCHED_RANGE_ATTACK2:
	case SCHED_MELEE_ATTACK1:
	case SCHED_MELEE_ATTACK2:
	case SCHED_TAKE_COVER_FROM_ENEMY:
		return SCHED_CONTROLLER_TAKECOVER;
	case SCHED_FAIL:
		return SCHED_CONTROLLER_FAIL;

	default:
		break;
	}

	return BaseClass::TranslateSchedule( scheduleType );
}


//=========================================================
// CheckRangeAttack1  - shoot a bigass energy ball out of their head
//=========================================================
int CNPC_Controller::RangeAttack1Conditions ( float flDot, float flDist )
{
	if( flDist > 2048 )
	{
		return COND_TOO_FAR_TO_ATTACK;
	}

	if( flDist <= 256 )
	{
		return COND_TOO_CLOSE_TO_ATTACK;
	}

//	if( flDot <= 0.5 )
//	{
//		return COND_NOT_FACING_ATTACK;
//	}

	return COND_CAN_RANGE_ATTACK1;
}

//=========================================================
// CheckRangeAttack1  - head
//=========================================================
int CNPC_Controller::RangeAttack2Conditions ( float flDot, float flDist )
{
		if( flDist > 2048 )
	{
		return COND_TOO_FAR_TO_ATTACK;
	}

	if( flDist <= 64 )
	{
		return COND_TOO_CLOSE_TO_ATTACK;
	}

//	if( flDot <= 0.5 )
//	{
//		return COND_NOT_FACING_ATTACK;
//	}

	return COND_CAN_RANGE_ATTACK2;
}

//=========================================================
// SetActivity  - 
//=========================================================
void CNPC_Controller::SetActivity ( Activity NewActivity )
{
	BaseClass::SetActivity( NewActivity );
	m_flGroundSpeed = 100;
}

//=========================================================
// RunAI
//=========================================================
void CNPC_Controller::RunAI( void )
{
	BaseClass::RunAI();

	Vector vecStart;
	QAngle angleGun;

	//some kind of hack in hl1 ?
//	if ( HasMemory( bits_MEMORY_KILLED ) )
	//use this instead
	if( !IsAlive() )
		return;

⌨️ 快捷键说明

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