Ejemplo n.º 1
0
//-----------------------------------------------------------------------------
// Purpose: Playback sound file that contains phonemes
// Input  : *actor - 
//			*parameters - 
//-----------------------------------------------------------------------------
void C_SceneEntity::DispatchStartSpeak( CChoreoScene *scene, C_BaseFlex *actor, CChoreoEvent *event, soundlevel_t iSoundlevel )
{
	// Emit sound
	if ( IsClientOnly() && actor )
	{
		CSingleUserRecipientFilter filter( C_BasePlayer::GetLocalPlayer() );

		float time_in_past = m_flCurrentTime - event->GetStartTime() ;
		float soundtime = gpGlobals->curtime - time_in_past;

		EmitSound_t es;
		es.m_nChannel = CHAN_VOICE;
		es.m_flVolume = 1;
		es.m_SoundLevel = iSoundlevel;
		es.m_flSoundTime = soundtime;

		// No CC since we do it manually
		// FIXME:  This will  change
		es.m_bEmitCloseCaption = false;
		es.m_pSoundName = event->GetParameters();

		EmitSound( filter, actor->entindex(), es );
		actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );

		// Close captioning only on master token no matter what...
		if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER )
		{
			char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ];
			bool validtoken = event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) );
			if ( validtoken )
			{
				CRC32_t tokenCRC;
				CRC32_Init( &tokenCRC );

				char lowercase[ 256 ];
				Q_strncpy( lowercase, tok, sizeof( lowercase ) );
				Q_strlower( lowercase );

				CRC32_ProcessBuffer( &tokenCRC, lowercase, Q_strlen( lowercase ) );
				CRC32_Final( &tokenCRC );

				float endtime = event->GetLastSlaveEndTime();
				float durationShort = event->GetDuration();
				float durationLong = endtime - event->GetStartTime();
				float duration = MAX( durationShort, durationLong );

				CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
				if ( hudCloseCaption )
				{
					hudCloseCaption->ProcessCaption( lowercase, duration );
				}
			}

		}
	}
}
	void EmitCloseCaption( IRecipientFilter& filter, int entindex, bool fromplayer, char const *token, CUtlVector< Vector >& originlist, float duration, bool warnifmissing /*= false*/ )
	{
		// No close captions in multiplayer...
		if ( gpGlobals->maxClients > 1 || (gpGlobals->maxClients==1 && !g_pClosecaption->GetBool()))
		{
			return;
		}

		// A negative duration means fill it in from the wav file if possible
		if ( duration < 0.0f )
		{
			char const *wav = soundemitterbase->GetWavFileForSound( token, GENDER_NONE );
			if ( wav )
			{
				duration = enginesound->GetSoundDuration( wav );
			}
			else
			{
				duration = 2.0f;
			}
		}

		char lowercase[ 256 ];
		Q_strncpy( lowercase, token, sizeof( lowercase ) );
		Q_strlower( lowercase );
		if ( Q_strstr( lowercase, "\\" ) )
		{
			Hack_FixEscapeChars( lowercase );
		}

		// NOTE:  We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing
		//  all players from it!!!!
		CRecipientFilter filterCopy;
		filterCopy.CopyFrom( (CRecipientFilter &)filter );

		// Remove any players who don't want close captions
		CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( (CRecipientFilter &)filterCopy );

#if !defined( CLIENT_DLL )
		{
			// Defined in sceneentity.cpp
			bool AttenuateCaption( const char *token, const Vector& listener, CUtlVector< Vector >& soundorigins );

			if ( filterCopy.GetRecipientCount() > 0 )
			{
				int c = filterCopy.GetRecipientCount();
				for ( int i = c - 1 ; i >= 0; --i )
				{
					CBasePlayer *player = UTIL_PlayerByIndex( filterCopy.GetRecipientIndex( i ) );
					if ( !player )
						continue;

					Vector playerOrigin = player->GetAbsOrigin();

					if ( AttenuateCaption( lowercase, playerOrigin, originlist ) )
					{
						filterCopy.RemoveRecipient( player );
					}
				}
			}
		}
#endif
		// Anyone left?
		if ( filterCopy.GetRecipientCount() > 0 )
		{

#if !defined( CLIENT_DLL )

			byte byteflags = 0;
			if ( warnifmissing )
			{
				byteflags |= CLOSE_CAPTION_WARNIFMISSING;
			}
			if ( fromplayer )
			{
				byteflags |= CLOSE_CAPTION_FROMPLAYER;
			}

			CBaseEntity *pActor = CBaseEntity::Instance( entindex );
			if ( pActor )
			{
				char const *pszActorModel = STRING( pActor->GetModelName() );
				gender_t gender = soundemitterbase->GetActorGender( pszActorModel );

				if ( gender == GENDER_MALE )
				{
					byteflags |= CLOSE_CAPTION_GENDER_MALE;
				}
				else if ( gender == GENDER_FEMALE )
				{ 
					byteflags |= CLOSE_CAPTION_GENDER_FEMALE;
				}
			}

			// Send caption and duration hint down to client
			UserMessageBegin( filterCopy, "CloseCaption" );
				WRITE_STRING( lowercase );
				WRITE_SHORT( MIN( 255, (int)( duration * 10.0f ) ) ),
				WRITE_BYTE( byteflags ),
			MessageEnd();
#else
			// Direct dispatch
			CHudCloseCaption *cchud = GET_HUDELEMENT( CHudCloseCaption );
			if ( cchud )
			{
				cchud->ProcessCaption( lowercase, duration, fromplayer );
			}
#endif
		}
	}