Exemple #1
0
void CGMan::RunTask(Task_t *pTask)
{
	switch(pTask->iTask)
	{
	case TASK_WAIT:
		// look at who I'm talking to
		if(m_flTalkTime > gpGlobals->time && m_hTalkTarget != NULL)
		{
			float yaw = VecToYaw(m_hTalkTarget->pev->origin - pev->origin) - pev->angles.y;

			if(yaw > 180)
				yaw -= 360;
			if(yaw < -180)
				yaw += 360;

			// turn towards vector
			SetBoneController(0, yaw);
		}
		// look at player, but only if playing a "safe" idle animation
		else if(m_hPlayer != NULL && pev->sequence == 0)
		{
			float yaw = VecToYaw(m_hPlayer->pev->origin - pev->origin) - pev->angles.y;

			if(yaw > 180)
				yaw -= 360;
			if(yaw < -180)
				yaw += 360;

			// turn towards vector
			SetBoneController(0, yaw);
		}
		else
		{
			SetBoneController(0, 0);
		}
		CBaseMonster::RunTask(pTask);
		break;
	default:
		SetBoneController(0, 0);
		CBaseMonster::RunTask(pTask);
		break;
	}
}
void CNPC_GMan :: RunTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_WAIT:
		// look at who I'm talking to
		if (m_flTalkTime > gpGlobals->curtime && m_hTalkTarget != NULL)
		{
			float yaw = VecToYaw(m_hTalkTarget->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y;

			if (yaw > 180) yaw -= 360;
			if (yaw < -180) yaw += 360;

			// turn towards vector
			SetBoneController( 0, yaw );
		}
		// look at player, but only if playing a "safe" idle animation
		else if (m_hPlayer != NULL && GetSequence() == 0)
		{
			float yaw = VecToYaw(m_hPlayer->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y;

			if (yaw > 180) yaw -= 360;
			if (yaw < -180) yaw += 360;

			// turn towards vector
			SetBoneController( 0, yaw );
		}
		else 
		{
			SetBoneController( 0, 0 );
		}
		BaseClass::RunTask( pTask );
		break;
	}

	SetBoneController( 0, 0 );
	BaseClass::RunTask( pTask );
}
Exemple #3
0
// turn head towards supplied origin
void CTalkMonster :: IdleHeadTurn( const Vector &vecFriend )
{
	 // turn head in desired direction only if ent has a turnable head
	if (m_afCapability & bits_CAP_TURN_HEAD)
	{
		float yaw = VecToYaw(vecFriend - GetAbsOrigin()) - GetAbsAngles().y;

		if (yaw > 180) yaw -= 360;
		if (yaw < -180) yaw += 360;

		// turn towards vector
		SetBoneController( 0, yaw );
	}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CAI_BaseFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget )
{
	float flDestYaw = VecToYaw( MoveTarget - GetLocalOrigin() );
	
	float newYaw = AI_ClampYaw( GetHeadTurnRate() * 10.0f, m_fHeadYaw, flDestYaw, gpGlobals->curtime - GetLastThink() );
		
	if ( newYaw != m_fHeadYaw )
	{
		m_fHeadYaw = newYaw;
	}

	// Set us to face that way
	SetBoneController( 0, m_fHeadYaw );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CAI_BasePhysicsFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget )
{
	float desYaw = UTIL_AngleDiff(VecToYaw(MoveTarget - GetLocalOrigin()), 0 );

	m_fHeadYaw = desYaw;

	return;

	// If I've flipped completely around, reverse angles
	float fYawDiff = m_fHeadYaw - desYaw;
	if (fYawDiff > 180)
	{
		m_fHeadYaw -= 360;
	}
	else if (fYawDiff < -180)
	{
		m_fHeadYaw += 360;
	}

	// RIGHT NOW, this affects every flying bot. This rate should be member data that individuals
	// can manipulate. THIS change for MANHACKS E3 2003 (sjb)
	float iRate = 0.8;

	// Make frame rate independent
	float timeToUse = flInterval;
	while (timeToUse > 0)
	{
		m_fHeadYaw	   = (iRate * m_fHeadYaw) + (1-iRate)*desYaw;
		timeToUse -= 0.1;
	}

	while( m_fHeadYaw > 360 )  
	{
		m_fHeadYaw -= 360.0f;
	}

	while( m_fHeadYaw < 0 )
	{
		m_fHeadYaw += 360.f;
	}

	// SetBoneController( 0, m_fHeadYaw );
}
Exemple #6
0
void CTalkMonster :: StartTask( const Task_t& task )
{
	switch ( task.iTask )
	{
	case TASK_TLK_SPEAK:
		// ask question or make statement
		FIdleSpeak();
		TaskComplete();
		break;

	case TASK_TLK_RESPOND:
		// respond to question
		IdleRespond();
		TaskComplete();
		break;

	case TASK_TLK_HELLO:
		// greet player
		FIdleHello();
		TaskComplete();
		break;
	

	case TASK_TLK_STARE:
		// let the player know I know he's staring at me.
		FIdleStare();
		TaskComplete();
		break;

	case TASK_FACE_PLAYER:
	case TASK_TLK_LOOK_AT_CLIENT:
	case TASK_TLK_CLIENT_STARE:
		// track head to the client for a while.
		m_flWaitFinished = gpGlobals->time + task.flData;
		break;

	case TASK_TLK_EYECONTACT:
		break;

	case TASK_TLK_IDEALYAW:
		if (m_hTalkTarget != NULL)
		{
			SetYawSpeed( 60 );
			float yaw = VecToYaw(m_hTalkTarget->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y;

			if (yaw > 180) yaw -= 360;
			if (yaw < -180) yaw += 360;

			if (yaw < 0)
			{
				SetIdealYaw( min( yaw + 45, 0.0f ) + GetAbsAngles().y );
			}
			else
			{
				SetIdealYaw( max( yaw - 45, 0.0f ) + GetAbsAngles().y );
			}
		}
		TaskComplete();
		break;

	case TASK_TLK_HEADRESET:
		// reset head position after looking at something
		m_hTalkTarget = NULL;
		TaskComplete();
		break;

	case TASK_TLK_STOPSHOOTING:
		// tell player to stop shooting
		PlaySentence( m_szGrp[TLK_NOSHOOT], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_NORM );
		TaskComplete();
		break;

	case TASK_CANT_FOLLOW:
		StopFollowing( false );
		PlaySentence( m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM );
		TaskComplete();
		break;

	case TASK_WALK_PATH_FOR_UNITS:
		m_movementActivity = ACT_WALK;
		break;

	case TASK_MOVE_AWAY_PATH:
		{
			Vector dir = GetAbsAngles();
			dir.y = GetIdealYaw() + 180;
			Vector move;

			UTIL_MakeVectorsPrivate( dir, &move, nullptr, nullptr );
			dir = GetAbsOrigin() + move * task.flData;
			if ( MoveToLocation( ACT_WALK, 2, dir ) )
			{
				TaskComplete();
			}
			else if ( FindCover( GetAbsOrigin(), GetViewOffset(), 0, CoverRadius() ) )
			{
				// then try for plain ole cover
				m_flMoveWaitFinished = gpGlobals->time + 2;
				TaskComplete();
			}
			else
			{
				// nowhere to go?
				TaskFail();
			}
		}
		break;

	case TASK_PLAY_SCRIPT:
		m_hTalkTarget = NULL;
		CBaseMonster::StartTask( task );
		break;

	default:
		CBaseMonster::StartTask( task );
	}
}
Exemple #7
0
void CMTalkMonster :: StartTask( Task_t *pTask )
{
	switch ( pTask->iTask )
	{
	case TASK_TLK_SPEAK:
		// ask question or make statement
		FIdleSpeak();
		TaskComplete();
		break;

	case TASK_TLK_RESPOND:
		// respond to question
		IdleRespond();
		TaskComplete();
		break;

	case TASK_TLK_HELLO:
		// greet player
		FIdleHello();
		TaskComplete();
		break;
	

	case TASK_TLK_STARE:
		// let the player know I know he's staring at me.
		FIdleStare();
		TaskComplete();
		break;

	case TASK_FACE_PLAYER:
	case TASK_TLK_LOOK_AT_CLIENT:
	case TASK_TLK_CLIENT_STARE:
		// track head to the client for a while.
		m_flWaitFinished = gpGlobals->time + pTask->flData;
		break;

	case TASK_TLK_EYECONTACT:
		break;

	case TASK_TLK_IDEALYAW:
		if (m_hTalkTarget != NULL)
		{
			pev->yaw_speed = 60;
			float yaw = VecToYaw(m_hTalkTarget->v.origin - pev->origin) - pev->angles.y;

			if (yaw > 180) yaw -= 360;
			if (yaw < -180) yaw += 360;

			if (yaw < 0)
			{
				pev->ideal_yaw = min( yaw + 45.0f, 0.0f ) + pev->angles.y;
			}
			else
			{
				pev->ideal_yaw = max( yaw - 45.0f, 0.0f ) + pev->angles.y;
			}
		}
		TaskComplete();
		break;

	case TASK_TLK_HEADRESET:
		// reset head position after looking at something
		m_hTalkTarget = NULL;
		TaskComplete();
		break;

	case TASK_TLK_STOPSHOOTING:
		// tell player to stop shooting
		PlaySentence( m_szGrp[TLK_NOSHOOT], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_NORM );
		TaskComplete();
		break;

	case TASK_CANT_FOLLOW:
		StopFollowing( FALSE );
		PlaySentence( m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM );
		TaskComplete();
		break;

	case TASK_WALK_PATH_FOR_UNITS:
		m_movementActivity = ACT_WALK;
		break;

	case TASK_MOVE_AWAY_PATH:
		{
			Vector dir = pev->angles;
			dir.y = pev->ideal_yaw + 180;
			Vector move;

			UTIL_MakeVectorsPrivate( dir, move, NULL, NULL );
			dir = pev->origin + move * pTask->flData;
			if ( MoveToLocation( ACT_WALK, 2, dir ) )
			{
				TaskComplete();
			}
			else if ( FindCover( pev->origin, pev->view_ofs, 0, CoverRadius() ) )
			{
				// then try for plain ole cover
				m_flMoveWaitFinished = gpGlobals->time + 2;
				TaskComplete();
			}
			else
			{
				// nowhere to go?
				TaskFail();
			}
		}
		break;

	case TASK_PLAY_SCRIPT:
		m_hTalkTarget = NULL;
		CMBaseMonster::StartTask( pTask );
		break;

	default:
		CMBaseMonster::StartTask( pTask );
	}
}
//=========================================================
// sit, do stuff
//=========================================================
void CSittingScientist :: SittingThink( void )
{
	CBaseEntity *pent;	

	StudioFrameAdvance( );

	// try to greet player
	if (FIdleHello())
	{
		pent = FindNearestFriend(TRUE);
		if (pent)
		{
			float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y;

			if (yaw > 180) yaw -= 360;
			if (yaw < -180) yaw += 360;
				
			if (yaw > 0)
				pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft;
			else
				pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright;
		
		ResetSequenceInfo( );
		pev->frame = 0;
		SetBoneController( 0, 0 );
		}
	}
	else if (m_fSequenceFinished)
	{
		int i = RANDOM_LONG(0,99);
		m_headTurn = 0;
		
		if (m_flResponseDelay && gpGlobals->time > m_flResponseDelay)
		{
			// respond to question
			IdleRespond();
			pev->sequence = m_baseSequence + SITTING_ANIM_sitscared;
			m_flResponseDelay = 0;
		}
		else if (i < 30)
		{
			pev->sequence = m_baseSequence + SITTING_ANIM_sitting3;	

			// turn towards player or nearest friend and speak

			if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer))
				pent = FindNearestFriend(TRUE);
			else
				pent = FindNearestFriend(FALSE);

			if (!FIdleSpeak() || !pent)
			{	
				m_headTurn = RANDOM_LONG(0,8) * 10 - 40;
				pev->sequence = m_baseSequence + SITTING_ANIM_sitting3;
			}
			else
			{
				// only turn head if we spoke
				float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y;

				if (yaw > 180) yaw -= 360;
				if (yaw < -180) yaw += 360;
				
				if (yaw > 0)
					pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft;
				else
					pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright;

				//ALERT(at_console, "sitting speak\n");
			}
		}
		else if (i < 60)
		{
			pev->sequence = m_baseSequence + SITTING_ANIM_sitting3;	
			m_headTurn = RANDOM_LONG(0,8) * 10 - 40;
			if (RANDOM_LONG(0,99) < 5)
			{
				//ALERT(at_console, "sitting speak2\n");
				FIdleSpeak();
			}
		}
		else if (i < 80)
		{
			pev->sequence = m_baseSequence + SITTING_ANIM_sitting2;
		}
		else if (i < 100)
		{
			pev->sequence = m_baseSequence + SITTING_ANIM_sitscared;
		}

		ResetSequenceInfo( );
		pev->frame = 0;
		SetBoneController( 0, m_headTurn );
	}
	SetNextThink( 0.1 );
}
void CNPC_Tentacle::Cycle( void )
{
	//NDebugOverlay::Cross3D( EarPosition(), 32, 255, 0, 0, false, 0.1 );

	// ALERT( at_console, "%s %.2f %d %d\n", STRING( pev->targetname ), pev->origin.z, m_MonsterState, m_IdealMonsterState );
	SetNextThink( gpGlobals->curtime + 0.1 );

	// ALERT( at_console, "%s %d %d %d %f %f\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim, m_iDir, pev->framerate, pev->health );

	if ( m_NPCState == NPC_STATE_SCRIPT || GetIdealState() == NPC_STATE_SCRIPT)
	{
		SetAbsAngles( QAngle( GetAbsAngles().x, m_flInitialYaw, GetAbsAngles().z ) );
		GetMotor()->SetIdealYaw( m_flInitialYaw );	
		RemoveIgnoredConditions();
		NPCThink( );
		m_iGoalAnim = TENTACLE_ANIM_Pit_Idle;
		return;
	}
	
	StudioFrameAdvance();
	DispatchAnimEvents( this );

	GetMotor()->UpdateYaw( MaxYawSpeed() );
	
	CSound *pSound = NULL;

	GetSenses()->Listen();
	m_BoneFollowerManager.UpdateBoneFollowers(this);

	// Listen will set this if there's something in my sound list
	if ( HeardAnything() )
		 pSound = GetSenses()->GetClosestSound( false, (SOUND_DANGER|SOUND_COMBAT|SOUND_WORLD|SOUND_PLAYER) );
	else
		 pSound = NULL;

	if ( pSound )
	{
		//NDebugOverlay::Line( EarPosition(), pSound->GetSoundOrigin(), 0, 255, 0, false, 0.2 );

		Vector vecDir;
		if ( gpGlobals->curtime - m_flPrevSoundTime < 0.5 )
		{
			float dt = gpGlobals->curtime - m_flPrevSoundTime;
			vecDir = pSound->GetSoundOrigin() + (pSound->GetSoundOrigin() - m_vecPrevSound) / dt - GetAbsOrigin();
		}
		else
		{
			vecDir = pSound->GetSoundOrigin() - GetAbsOrigin();
		}

		m_flPrevSoundTime = gpGlobals->curtime;
		m_vecPrevSound = pSound->GetSoundOrigin();

		m_flSoundYaw = VecToYaw ( vecDir ) - m_flInitialYaw;

		m_iSoundLevel = Level( vecDir.z );

		if (m_flSoundYaw < -180)
			m_flSoundYaw += 360;
		if (m_flSoundYaw > 180)
			m_flSoundYaw -= 360;

		// ALERT( at_console, "sound %d %.0f\n", m_iSoundLevel, m_flSoundYaw );
		if (m_flSoundTime < gpGlobals->curtime)
		{
			// play "I hear new something" sound
			 UTIL_EmitAmbientSound( GetSoundSourceIndex(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), "Tentacle.Alert", 1.0, SNDLVL_GUNFIRE, 0, 100);
		}
		m_flSoundTime = gpGlobals->curtime + random->RandomFloat( 5.0, 10.0 );
	}

	// clip ideal_yaw
	float dy = m_flSoundYaw;
	switch( GetSequence() )
	{
	case TENTACLE_ANIM_Floor_Rear:
	case TENTACLE_ANIM_Floor_Rear_Idle:
	case TENTACLE_ANIM_Lev1_Rear:
	case TENTACLE_ANIM_Lev1_Rear_Idle:
	case TENTACLE_ANIM_Lev2_Rear:
	case TENTACLE_ANIM_Lev2_Rear_Idle:
	case TENTACLE_ANIM_Lev3_Rear:
	case TENTACLE_ANIM_Lev3_Rear_Idle:
		if (dy < 0 && dy > -m_flMaxYaw)
			dy = -m_flMaxYaw;
		if (dy > 0 && dy < m_flMaxYaw)
			dy = m_flMaxYaw;
		break;
	default:
		if (dy < -m_flMaxYaw)
			dy = -m_flMaxYaw;
		if (dy > m_flMaxYaw)
			dy = m_flMaxYaw;
	}
	GetMotor()->SetIdealYaw( m_flInitialYaw + dy );

	if ( IsSequenceFinished() )
	{
		// ALERT( at_console, "%s done %d %d\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim );
		if ( m_iHealth <= 1)
		{
			m_iGoalAnim = TENTACLE_ANIM_Pit_Idle;

			if ( GetSequence() == TENTACLE_ANIM_Pit_Idle)
			{
				m_iHealth = 75;
			}
		}
		else if ( m_flSoundTime > gpGlobals->curtime )
		{
			if (m_flSoundYaw >= -(m_flMaxYaw + 30) && m_flSoundYaw <= (m_flMaxYaw + 30))
			{
				// strike
				switch ( m_iSoundLevel )
				{
					case 0:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1030 );
						break;
					case 1:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1031 );
						break;
					case 2:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1032 );
						break;
					case 3:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1033 );
						break;
				}
			}
			else if (m_flSoundYaw >= -m_flMaxYaw * 2 && m_flSoundYaw <= m_flMaxYaw * 2) 
			{
				// tap
				switch ( m_iSoundLevel )
				{
					case 0:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1020 );
						break;
					case 1:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1021 );
						break;
					case 2:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1022 );
						break;
					case 3:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1023 );
						break;
				}
			}
			else
			{
				// go into rear idle
				switch ( m_iSoundLevel )
				{
					case 0:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1040 );
						break;
					case 1:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1041 );
						break;
					case 2:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1042 );
						break;
					case 3:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1043 );
						break;
					case 4:
						m_iGoalAnim = SelectWeightedSequence ( ACT_1044 );
						break;
				}
			}
		}
		else if ( GetSequence() == TENTACLE_ANIM_Pit_Idle)
		{
			// stay in pit until hear noise
			m_iGoalAnim = TENTACLE_ANIM_Pit_Idle;
		}
		else if ( GetSequence() == m_iGoalAnim)
		{
			if ( MyLevel() >= 0 && gpGlobals->curtime < m_flSoundTime)
			{
				if ( random->RandomInt(0,9) < m_flSoundTime - gpGlobals->curtime )
				{
					// continue stike
					switch ( m_iSoundLevel )
					{
						case 0:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1030 );
							break;
						case 1:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1031 );
							break;
						case 2:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1032 );
							break;
						case 3:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1033 );
							break;
					}
				}
				else
				{
					// tap
					switch ( m_iSoundLevel )
					{
						case 0:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1020 );
							break;
						case 1:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1021 );
							break;
						case 2:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1022 );
							break;
						case 3:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1023 );
							break;
					}
				}
			}
			else if ( MyLevel( ) < 0 )
			{
				m_iGoalAnim = SelectWeightedSequence( ACT_1010 );
			}
			else
			{
				if (m_flNextSong < gpGlobals->curtime)
				{
					// play "I hear new something" sound
					CPASAttenuationFilter filter( this );
					EmitSound( filter, entindex(), "Tentacle.Sing" );

					m_flNextSong = gpGlobals->curtime + random->RandomFloat( 10, 20 );
				}

				if (random->RandomInt(0,15) == 0)
				{
					// idle on new level
					switch ( random->RandomInt( 0, 3 ) )
					{
						case 0:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1010 );
							break;
						case 1:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1011 );
							break;
						case 2:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1012 );
							break;
						case 3:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1013 );
							break;
					}
				}
				else if ( random->RandomInt( 0, 3 ) == 0 )
				{
					// tap
					switch ( MyLevel() )
					{
						case 0:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1020 );
							break;
						case 1:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1021 );
							break;
						case 2:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1022 );
							break;
						case 3:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1023 );
							break;
					}
				}
				else
				{
					// idle
					switch ( MyLevel() )
					{
						case 0:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1010 );
							break;
						case 1:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1011 );
							break;
						case 2:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1012 );
							break;
						case 3:
							m_iGoalAnim = SelectWeightedSequence ( ACT_1013 );
							break;
					}
				}
			}
			if (m_flSoundYaw < 0)
				m_flSoundYaw += random->RandomFloat( 2, 8 );
			else
				m_flSoundYaw -= random->RandomFloat( 2, 8 );
		}

		SetSequence( FindTransitionSequence( GetSequence(), m_iGoalAnim, &m_iDir ) );
		

		if (m_iDir > 0)
		{
			SetCycle( 0 );
		}
		else
		{
			m_iDir = -1; // just to safe
			SetCycle( 1.0f );
		}

		ResetSequenceInfo( );

		m_flFramerateAdj = random->RandomFloat( -0.2, 0.2 );
		m_flPlaybackRate = m_iDir * 1.0 + m_flFramerateAdj;

		switch( GetSequence() )
		{
		case TENTACLE_ANIM_Floor_Tap:
		case TENTACLE_ANIM_Lev1_Tap:
		case TENTACLE_ANIM_Lev2_Tap:
		case TENTACLE_ANIM_Lev3_Tap:
			{
				Vector vecSrc, v_forward;
				AngleVectors( GetAbsAngles(), &v_forward );

				trace_t tr1, tr2;

				vecSrc = GetAbsOrigin() + Vector( 0, 0, MyHeight() - 4);
				UTIL_TraceLine( vecSrc, vecSrc + v_forward * 512, MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr1 );

				vecSrc = GetAbsOrigin() + Vector( 0, 0, MyHeight() + 8);
				UTIL_TraceLine( vecSrc, vecSrc + v_forward * 512, MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr2 );

				// ALERT( at_console, "%f %f\n", tr1.flFraction * 512, tr2.flFraction * 512 );

				m_flTapRadius = SetPoseParameter( 0, random->RandomFloat( tr1.fraction * 512, tr2.fraction * 512 ) );
			}
			break;
		default:
			m_flTapRadius = 336; // 400 - 64
			break;
		}
		SetViewOffset( Vector( 0, 0, MyHeight() ) );
		// ALERT( at_console, "seq %d\n", pev->sequence );
	}

	if (m_flPrevSoundTime + 2.0 > gpGlobals->curtime)
	{
		// 1.5 normal speed if hears sounds
		m_flPlaybackRate = m_iDir * 1.5 + m_flFramerateAdj;
	}
	else if (m_flPrevSoundTime + 5.0 > gpGlobals->curtime)
	{
		// slowdown to normal
		m_flPlaybackRate = m_iDir + m_iDir * (5 - (gpGlobals->curtime - m_flPrevSoundTime)) / 2 + m_flFramerateAdj;
	}
}