//-----------------------------------------------------------------------------
// Purpose: 
//
//
// Output : 
//-----------------------------------------------------------------------------
void CNPC_RollerDozer::RunTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_ROLLERDOZER_CLEAR_DEBRIS:
		if( gpGlobals->curtime > m_flWaitFinished )
		{
			m_hDebris = NULL;
			m_flTimeDebrisSearch = gpGlobals->curtime;
			TaskComplete();
		}
		else if( m_hDebris != NULL )
		{
			float yaw = UTIL_VecToYaw( m_hDebris->GetLocalOrigin() - GetLocalOrigin() );
			Vector vecRight, vecForward;

			AngleVectors( QAngle( 0, yaw, 0 ), &vecForward, &vecRight, NULL );

			//Stop pushing if I'm going to push this object sideways or back towards the center of the cleanup area.
			Vector vecCleanupDir = m_hDebris->GetLocalOrigin() - m_vecCleanupPoint;
			VectorNormalize( vecCleanupDir );
			if( DotProduct( vecForward, vecCleanupDir ) < -0.5 )
			{
				// HACKHACK !!!HACKHACK - right now forcing an unstick. Do this better (sjb)

				// Clear the debris, suspend the search for debris, trick base class into unsticking me.
				m_hDebris = NULL;
				m_flTimeDebrisSearch = gpGlobals->curtime + 4;
				m_iFail = 10;
				TaskFail("Pushing Wrong Way");
			}

			m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, ROLLERDOZER_FORWARD_SPEED * 2 );
		}
		else
		{
			TaskFail("No debris!!");
		}

		break;

	default:
		BaseClass::RunTask( 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;
	}
}
static int vmatrix_SetupMatrixAngles (lua_State *L) {
  lua_pushvmatrix(L, SetupMatrixAngles(luaL_checkangle(L, 1)));
  return 1;
}