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

📄 npc_roller.cpp

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


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::MarcoSound( void )
{
	if( gpGlobals->curtime < m_flTimeMarcoSound )
	{
		return;
	}

	EmitSound( "NPC_Roller.Marco" );


	// Look for all the other rollers in the effective radius and tell them to polo me.
	CBaseEntity *pEntity = gEntList.FindEntityByClassname(  NULL, "npc_roller" );
	while( pEntity )
	{
		if( UTIL_DistApprox( GetAbsOrigin(), pEntity->GetAbsOrigin() ) <= ROLLER_MARCOPOLO_DIST )
		{
			CNPC_Roller *pRoller;

			pRoller = dynamic_cast<CNPC_Roller *>(pEntity);

			if( pRoller && pRoller != this )
			{
				// Don't interfere with a roller that's 
				// supposed to be replying to someone else.
				if( pRoller->m_flTimePoloSound == TIME_NEVER )
				{
					// Tell this Roller to polo in a couple seconds.
					pRoller->m_flTimePoloSound = gpGlobals->curtime + 1 + random->RandomFloat( 0, 2 );

					// Tell him also not to marco for quite some time.
					pRoller->m_flTimeMarcoSound = gpGlobals->curtime + ROLLER_MARCO_FREQUENCY * 2;
				}
			}
		}

		pEntity = gEntList.FindEntityByClassname( pEntity, "npc_roller" );
	}
	
	
	
	m_flTimeMarcoSound = gpGlobals->curtime + ROLLER_MARCO_FREQUENCY;
}


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::PoloSound( void )
{
	if( gpGlobals->curtime < m_flTimePoloSound )
	{
		return;
	}

	EmitSound( "NPC_Roller.Polo" );

	m_flTimePoloSound = TIME_NEVER;
}


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::PrescheduleThink( void )
{
	BaseClass::PrescheduleThink();
	
#if 0
	MarcoSound();
	PoloSound();
#endif
}


//---------------------------------------------------------
//---------------------------------------------------------
int CNPC_Roller::SelectSchedule ( void )
{
	if( m_fHACKJustSpawned )
	{
		m_fHACKJustSpawned = false;
		return SCHED_ROLLER_WAIT_FOR_PHYSICS;
	}

	switch( m_NPCState )
	{
	case NPC_STATE_COMBAT:
		if( HasCondition( COND_ROLLER_PHYSICS ) )
		{
			return SCHED_ROLLER_WAIT_FOR_PHYSICS;
		}
		break;

	default:
		if( HasCondition( COND_ROLLER_PHYSICS ) )
		{
			return SCHED_ROLLER_WAIT_FOR_PHYSICS;
		}

		return SCHED_IDLE_STAND;
		break;
	}

	return SCHED_IDLE_STAND;
}


//---------------------------------------------------------
//---------------------------------------------------------
int CNPC_Roller::TranslateSchedule( int scheduleType ) 
{
	switch( scheduleType )
	{
	case SCHED_CHASE_ENEMY_FAILED:
	case SCHED_FAIL:
		if( m_iFail > ROLLER_NUM_FAILS )
		{
			// If the roller has failed a lot, try to unstick him. 
			// Usually by rolling backwards.
			return SCHED_ROLLER_UNSTICK;
		}
		else
		{
			return SCHED_FAIL;
		}

		break;

	case SCHED_IDLE_STAND:
		// Don't stand around. Patrol.
		return SCHED_ROLLER_PATROL;
		break;
	}
	return BaseClass::TranslateSchedule( scheduleType );
}


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::StartTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_ROLLER_ON:
		PowerOn();
		TaskComplete();
		break;

	case TASK_ROLLER_OFF:
		PowerOff();
		TaskComplete();
		break;

	case TASK_ROLLER_WAIT_FOR_PHYSICS:
		// Stop rolling.
		m_flWaitFinished = gpGlobals->curtime;
		m_RollerController.m_vecAngular = vec3_origin;
		PowerOff();
		break;

	case TASK_ROLLER_FIND_PATROL_NODE:

		m_pHintNode = CAI_Hint::FindHint( this, HINT_ROLLER_PATROL_POINT, 0, 1024 ); 

		if(!m_pHintNode)
		{
			TaskFail("Couldn't find roller patrol node");
		}
		else
		{
			TaskComplete();
		}
		break;

	case TASK_ROLLER_UNSTICK:
		Unstick();

		if( m_vecUnstickDirection == vec3_origin )
		{
			TaskComplete();
		}
		else
		{
			VPhysicsGetObject()->Wake();
			PowerOn();
			
			// Cut back on the fail count, but not all the way.
			// Only a successful opportunity move sets this to 0.
			m_iFail /= 2;

			m_flWaitFinished = gpGlobals->curtime + 2;
		}

		break;

	case TASK_WALK_PATH:
	case TASK_RUN_PATH:
		// Make sure the controller isn't turned off.
		m_iFail = 0; // Successfully starting to move.
		VPhysicsGetObject()->Wake();
		PowerOn();
		break;

	case TASK_ROLLER_ISSUE_CODE:
		m_iCodeProgress = 0;
		m_flWaitFinished = gpGlobals->curtime;
		break;

	default:
		BaseClass::StartTask( pTask );
		break;
	}
}


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::RunTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_ROLLER_UNSTICK:
		{
			float yaw = UTIL_VecToYaw( m_vecUnstickDirection );

			Vector vecRight;
			AngleVectors( QAngle( 0, yaw, 0 ), NULL, &vecRight, NULL );
			m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed );
		}
			
		if( gpGlobals->curtime > m_flWaitFinished )
		{
			TaskComplete();
		}
		break;

	case TASK_ROLLER_WAIT_FOR_PHYSICS:
		{
			Vector vecVelocity;

			VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL );

			if( VPhysicsGetObject()->IsAsleep() )
			{
				TaskComplete();
			}
		}
		break;

	case TASK_RUN_PATH:
	case TASK_WALK_PATH:

		// Start turning early
		if( (GetLocalOrigin() - GetNavigator()->GetCurWaypointPos() ).Length() <= 64 )
		{
			if( GetNavigator()->CurWaypointIsGoal() )
			{
				// Hit the brakes a bit.
				float yaw = UTIL_VecToYaw( GetNavigator()->GetCurWaypointPos() - GetLocalOrigin() );
				Vector vecRight;
				AngleVectors( QAngle( 0, yaw, 0 ), NULL, &vecRight, NULL );

				m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, -m_flForwardSpeed * 5 );

				TaskComplete();
				return;
			}

			GetNavigator()->AdvancePath();	
		}

		{
			float yaw = UTIL_VecToYaw( GetNavigator()->GetCurWaypointPos() - GetLocalOrigin() );

			Vector vecRight;
			Vector vecToPath; // points at the path
			AngleVectors( QAngle( 0, yaw, 0 ), &vecToPath, &vecRight, NULL );

			// figure out if the roller is turning. If so, cut the throttle a little.
			float flDot;
			Vector vecVelocity;
			VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL );

			VectorNormalize( vecVelocity );

			vecVelocity.z = 0;

			flDot = DotProduct( vecVelocity, vecToPath );

			m_RollerController.m_vecAngular = vec3_origin;

			if( flDot > 0.25 && flDot < 0.7 )
			{
				// Feed a little torque backwards into the axis perpendicular to the velocity.
				// This will help get rid of momentum that would otherwise make us overshoot our goal.
				Vector vecCompensate;

				vecCompensate.x = vecVelocity.y;
				vecCompensate.y = -vecVelocity.x;
				vecCompensate.z = 0;

				m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecCompensate, m_flForwardSpeed * -0.75 );
			}

			m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed );
		}
		break;

	case TASK_ROLLER_ISSUE_CODE:
		if( gpGlobals->curtime >= m_flWaitFinished )
		{
			if( m_iCodeProgress == ROLLER_CODE_DIGITS )
			{
				TaskComplete();
			}
			else
			{
				m_flWaitFinished = gpGlobals->curtime + ROLLER_TONE_TIME;
				CPASAttenuationFilter filter( this );
				EmitSound( filter, entindex(), CHAN_BODY, pCodeSounds[ m_iAccessCode[ m_iCodeProgress ] ], 1.0, ATTN_NORM );
				m_iCodeProgress++;
			}
		}
		break;

	default:
		BaseClass::RunTask( pTask );
		break;
	}
}


//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_Roller::IsBlocked( const Vector &vecCheck )
{
	trace_t tr;

	return false;

#if 0
	NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin() + vecCheck, 255,255,0, true, 0.1 );
	
	Vector vecRight;
	Vector vecForward;

	AngleVectors( GetLocalAngles(), &vecForward, &vecRight, NULL );

	NDebugOverlay::Line( GetLocalOrigin() + vecRight * 32, GetLocalOrigin() + vecRight * -32, 0,255,0, true, 0.1 );

#endif ROLLER_DEBUG

	AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecCheck, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
	return ( tr.fraction != 1.0 );
}


//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_Roller::IsBlockedForward( void )
{
	Vector vecLinear;

	VPhysicsGetObject()->GetVelocity( &vecLinear, NULL );

	VectorNormalize( vecLinear );

	vecLinear *= ROLLER_CHECK_DIST;

	return IsBlocked( vecLinear );
}


//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_Roller::IsBlockedBackward( void )
{
	Vector vecLinear;
	VPhysicsGetObject()->GetVelocity( &vecLinear, NULL );

	VectorNormalize( vecLinear );

	vecLinear *= ROLLER_CHECK_DIST;

	return IsBlocked( vecLinear );
}


//---------------------------------------------------------
//---------------------------------------------------------
int CNPC_Roller::VPhysicsTakeDamage( const CTakeDamageInfo &info )
{
	if( RollerPhysicsDamageMask() & info.GetDamageType() )
	{
		SetCondition( COND_ROLLER_PHYSICS );
	}

	return BaseClass::VPhysicsTakeDamage( info );
}


//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_Roller::OverrideMove( float flInterval )
{
	// Do nothing
	return true;
}


//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Roller::TaskFail( AI_TaskFailureCode_t code )
{
	const Task_t *pTask = GetTask();

	if( pTask )
	{
		Msg( "Failed to: %s\n", TaskName( pTask->iTask ) );

		switch( pTask->iTask )
		{
		case TASK_WALK_PATH:
		case TASK_RUN_PATH:
		case TASK_GET_PATH_TO_ENEMY:
		case TASK_GET_PATH_TO_ENEMY_LKP:
		case TASK_GET_PATH_TO_HINTNODE:
			m_iFail++;
			break;
		}
	}

	BaseClass::TaskFail( code );
}


//-----------------------------------------------------------------------------
//
// Schedules
//
//-----------------------------------------------------------------------------

//=========================================================
// Patrol - roll around from hint node to hint node.
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_ROLLER_PATROL,

	"	Tasks"
	"		TASK_ROLLER_FIND_PATROL_NODE	0"
	"		TASK_GET_PATH_TO_HINTNODE		0"
	"		TASK_WALK_PATH					0"
	"	"
	"	Interrupts"
	"		COND_NEW_ENEMY"
	"		COND_ROLLER_PHYSICS"
	"		COND_CAN_RANGE_ATTACK1"
);

//=========================================================
// Unstick - try to get unstuck.
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_ROLLER_UNSTICK,

	"	Tasks"
	"		TASK_ROLLER_UNSTICK				0"
	"	"
	"	Interrupts"
	"		COND_ROLLER_PHYSICS"
);

//=========================================================
// WAIT_FOR_PHYSICS
//
// Don't do ANYTHING until done simulating.
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_ROLLER_WAIT_FOR_PHYSICS,

	"	Tasks"
	"		TASK_ROLLER_WAIT_FOR_PHYSICS 0"
	"	"
	"	Interrupts"
);


⌨️ 快捷键说明

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