void CAI_Expresser::ForceNotSpeaking( void )
{
	if ( IsSpeaking() )
	{
		m_flStopTalkTime = gpGlobals->curtime;
		m_flStopTalkTimeWithoutDelay = gpGlobals->curtime;

		CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( GetOuter() );
		if ( pSemaphore )
		{
			if ( pSemaphore->GetOwner() == GetOuter() )
			{
				pSemaphore->Release();
			}
		}
	}
}
void CAI_LeadBehavior::RunTask( const Task_t *pTask )		
{ 
	switch ( pTask->iTask )
	{
		case TASK_LEAD_SUCCEED:
		{
			if ( !IsSpeaking() )
			{
				TaskComplete();
				NotifyEvent( LBE_DONE );
			}
			break;
		}
		case TASK_LEAD_ARRIVE:
		{
			if ( !IsSpeaking() )
			{
				TaskComplete();
				NotifyEvent( LBE_ARRIVAL_DONE );
			}
			break;
		}

		case TASK_LEAD_MOVE_TO_RANGE:
		{
			// If we haven't spoken our start speech, move closer
 			if ( !m_hasspokenstart)
			{
				ChainRunTask( TASK_MOVE_TO_GOAL_RANGE, m_leaddistance - 24 );
			}
			else
			{
 				ChainRunTask( TASK_MOVE_TO_GOAL_RANGE, m_retrievedistance );

				if ( !TaskIsComplete() )
				{
					// Transition to a walk when we get near the player
					// Check Z first, and only check 2d if we're within that
					Vector vecGoalPos = GetNavigator()->GetGoalPos();
					float distance = fabs(vecGoalPos.z - GetLocalOrigin().z);
					bool bWithinZ = false;
					if ( distance < m_retrievedistance )
					{
						distance = ( vecGoalPos - GetLocalOrigin() ).Length2D();
						bWithinZ = true;
					}

					if ( distance > m_retrievedistance )
					{
						Activity followActivity = ACT_WALK;
						if ( GetOuter()->GetState() == NPC_STATE_COMBAT || ( (!bWithinZ || distance < (m_retrievedistance*4)) && GetOuter()->GetState() != NPC_STATE_COMBAT ) )
						{
							followActivity = ACT_RUN;
						}

						// Don't confuse move and shoot by resetting the activity every think
						Activity curActivity = GetNavigator()->GetMovementActivity();
						switch( curActivity )
						{
						case ACT_WALK_AIM:	curActivity = ACT_WALK;	break;
						case ACT_RUN_AIM:	curActivity = ACT_RUN;	break;
						}
						
						if ( curActivity != followActivity )
						{
							GetNavigator()->SetMovementActivity(followActivity);
						}
						GetNavigator()->SetArrivalDirection( GetOuter()->GetTarget() );
					}
				}
			}
			break;
		}

		case TASK_LEAD_RETRIEVE_WAIT:
		{
			ChainRunTask( TASK_WAIT_INDEFINITE );
			break;
		}

		case TASK_LEAD_WALK_PATH:
		{
			// If we're leading, and we're supposed to run, run instead of walking
			if ( m_run && 
				( IsCurSchedule( SCHED_LEAD_WAITFORPLAYER, false ) || IsCurSchedule( SCHED_LEAD_PLAYER, false ) || IsCurSchedule( SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, false )|| IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) ) )
			{
				ChainRunTask( TASK_RUN_PATH );
			}
			else
			{
				ChainRunTask( TASK_WALK_PATH );
			}

			// While we're walking
			if ( TaskIsRunning() && IsCurSchedule( SCHED_LEAD_PLAYER, false ) )
			{
				// If we're not speaking, and we haven't tried for a while, try to speak lead idle
				if ( m_flNextLeadIdle < gpGlobals->curtime && !IsSpeaking() )
				{
					m_flNextLeadIdle = gpGlobals->curtime + RandomFloat( 10,15 );

					if ( !m_args.iRetrievePlayer && HasCondition( COND_LEAD_FOLLOWER_LOST ) && HasCondition(COND_SEE_PLAYER) )
					{
						Speak( TLK_LEAD_COMINGBACK );
					}
					else
					{
						Speak( TLK_LEAD_IDLE );
					}
				}
			}

			break;
		}

		default:
			BaseClass::RunTask( pTask);
	}
}
int CAI_LeadBehavior::SelectSchedule()
{
	if ( HasGoal() )
	{
		if( HasCondition(COND_LEAD_SUCCESS) )
		{
			return SCHED_LEAD_SUCCEED;
		}

		// Player's here, but does he have the weapon we want him to have?
		if ( m_weaponname != NULL_STRING )
		{
			CBasePlayer *pFollower = AI_GetSinglePlayer();
			if ( pFollower && !pFollower->Weapon_OwnsThisType( STRING(m_weaponname) ) )
			{
				// If the safety timeout has run out, just give the player the weapon
				if ( !m_flWeaponSafetyTimeOut || (m_flWeaponSafetyTimeOut > gpGlobals->curtime) )
					return SCHED_LEAD_PLAYERNEEDSWEAPON;

				string_t iszItem = AllocPooledString( "weapon_bugbait" );
				pFollower->GiveNamedItem( STRING(iszItem) );
			}
		}

		// If we have a waitpoint, we want to wait at it for the player.
		if( HasWaitPoint() && !PlayerIsAheadOfMe( true ) )
		{
			bool bKeepWaiting = true;

			// If we have no wait distance, trigger as soon as the player comes in view
			if ( !m_waitdistance )
			{
				if ( HasCondition( COND_SEE_PLAYER ) )
				{
					// We've spotted the player, so stop waiting
					bKeepWaiting = false;
				}
			}
			else
			{
				// We have to collect data about the person we're leading around.
				CBaseEntity *pFollower = AI_GetSinglePlayer();
				if( pFollower )
				{
					float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length();
					if ( flFollowerDist < m_waitdistance )
					{
						bKeepWaiting = false;
					}
				}
			}

			// Player still not here?
			if ( bKeepWaiting )
				return SCHED_LEAD_WAITFORPLAYER;

			// We're finished waiting
			m_waitpoint = vec3_origin;
			Speak( TLK_LEAD_WAITOVER );

			// Don't speak the start line, because we've said 
			m_hasspokenstart = true;
			return SCHED_WAIT_FOR_SPEAK_FINISH;
		}

		// If we haven't spoken our start speech, do that first
		if ( !m_hasspokenstart )
		{
			if ( HasCondition(COND_LEAD_HAVE_FOLLOWER_LOS) && HasCondition(COND_LEAD_FOLLOWER_VERY_CLOSE) )
				return SCHED_LEAD_SPEAK_START;

			// We haven't spoken to him, and we still need to. Go get him.
			return SCHED_LEAD_RETRIEVE;
		}

		if( HasCondition( COND_LEAD_FOLLOWER_LOST ) )
		{
			if( m_args.iRetrievePlayer )
			{
				// If not, we want to go get the player.
				DevMsg( GetOuter(), "Follower lost. Spoke COMING_BACK.\n");

				Speak( TLK_LEAD_COMINGBACK );
				m_MoveMonitor.ClearMark();

				// If we spoke something, wait for it to finish
				if ( m_args.iComingBackWaitForSpeak && IsSpeaking() )
					return SCHED_LEAD_SPEAK_THEN_RETRIEVE_PLAYER;

				return SCHED_LEAD_RETRIEVE;
			}
			else
			{
				// Just stay right here and wait.
				return SCHED_LEAD_WAITFORPLAYERIDLE;
			}
		}

		if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) )
		{
			DevMsg( GetOuter(), "Follower lagging. Spoke CATCHUP.\n");

			Speak( TLK_LEAD_CATCHUP );
			return SCHED_LEAD_PAUSE;
		}
		else
		{
			// If we're at the goal, wait for the player to get here
			if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() < (64*64) )
				return SCHED_LEAD_AWAIT_SUCCESS;

			// If we were retrieving the player, speak the resume
			if ( IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) || IsCurSchedule( SCHED_LEAD_WAITFORPLAYERIDLE, false ) )
			{
				Speak( TLK_LEAD_RETRIEVE );

				// If we spoke something, wait for it to finish, if the mapmakers wants us to
				if ( m_args.iRetrieveWaitForSpeak && IsSpeaking() )
					return SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER;
			}

			DevMsg( GetOuter(), "Leading Follower.\n");
			return SCHED_LEAD_PLAYER;
		}
	}
	return BaseClass::SelectSchedule();
}
//-----------------------------------------------------------------------------
// Purpose: Dispatches the result
// Input  : *response - 
//-----------------------------------------------------------------------------
bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter /* = NULL */ )
{
	char response[ 256 ];
	result->GetResponse( response, sizeof( response ) );

	float delay = result->GetDelay();
	
	bool spoke = false;

	soundlevel_t soundlevel = result->GetSoundLevel();

	if ( IsSpeaking() && concept[0] != 0 )
	{
		DevMsg( "SpeakDispatchResponse:  Entity ( %i/%s ) already speaking, forcing '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), concept );

		// Tracker 15911:  Can break the game if we stop an imported map placed lcs here, so only
		//  cancel actor out of instanced scripted scenes.  ywb
		RemoveActorFromScriptedScenes( GetOuter(), true /*instanced scenes only*/ );
		GetOuter()->SentenceStop();

		if ( IsRunningScriptedScene( GetOuter() ) )
		{
			DevMsg( "SpeakDispatchResponse:  Entity ( %i/%s ) refusing to speak due to scene entity, tossing '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), concept );
			delete result;
			return false;
		}
	}

	switch ( result->GetType() )
	{
	default:
	case RESPONSE_NONE:
		break;

	case RESPONSE_SPEAK:
		{
			if ( !result->ShouldntUseScene() )
			{
				// This generates a fake CChoreoScene wrapping the sound.txt name
				spoke = SpeakAutoGeneratedScene( response, delay );
			}
			else
			{
				float speakTime = GetResponseDuration( result );
				GetOuter()->EmitSound( response );

				DevMsg( "SpeakDispatchResponse:  Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), response );
				NoteSpeaking( speakTime, delay );
				spoke = true;
			}
		}
		break;

	case RESPONSE_SENTENCE:
		{
			spoke = ( -1 != SpeakRawSentence( response, delay, VOL_NORM, soundlevel ) ) ? true : false;
		}
		break;

	case RESPONSE_SCENE:
		{
			spoke = SpeakRawScene( response, delay, result, filter );
		}
		break;

	case RESPONSE_RESPONSE:
		{
			// This should have been recursively resolved already
			Assert( 0 );
		}
		break;
	case RESPONSE_PRINT:
		{
			if ( g_pDeveloper->GetInt() > 0 )
			{
				Vector vPrintPos;
				GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos );
				NDebugOverlay::Text( vPrintPos, response, true, 1.5 );
				spoke = true;
			}
		}
		break;
	}

	if ( spoke )
	{
		m_flLastTimeAcceptedSpeak = gpGlobals->curtime;
		if ( DebuggingSpeech() && g_pDeveloper->GetInt() > 0 && response && result->GetType() != RESPONSE_PRINT )
		{
			Vector vPrintPos;
			GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos );
			NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, response ), true, 1.5 );
		}

		if ( result->IsApplyContextToWorld() )
		{
			CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) );
			if ( pEntity )
			{
				pEntity->AddContext( result->GetContext() );
			}
		}
		else
		{
			GetOuter()->AddContext( result->GetContext() );
		}
		SetSpokeConcept( concept, result );
	}
	else
	{
		delete result;
	}

	return spoke;
}