bool CHLTVDirector::SetCameraMan( int iPlayerIndex ) { if ( !tv_allow_camera_man.GetBool() ) return false; if ( m_iCameraManIndex == iPlayerIndex ) return true; // check if somebody else is already the camera man if ( m_iCameraManIndex != 0 && iPlayerIndex != 0 ) return false; CBasePlayer *pPlayer = NULL; if ( iPlayerIndex > 0 ) { pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); if ( !pPlayer || pPlayer->GetTeamNumber() != TEAM_SPECTATOR ) return false; } m_iCameraManIndex = iPlayerIndex; // create event for director event history IGameEvent *event = gameeventmanager->CreateEvent( "hltv_cameraman" ); if ( event ) { event->SetInt("index", iPlayerIndex ); gameeventmanager->FireEvent( event ); } CRecipientFilter filter; for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); if ( pPlayer && pPlayer->GetTeamNumber() == TEAM_SPECTATOR && !pPlayer->IsFakeClient() ) { filter.AddRecipient( pPlayer ); } } filter.MakeReliable(); if ( iPlayerIndex > 0 ) { // tell all spectators that the camera is avaliable again. char szText[200]; Q_snprintf( szText, sizeof(szText), "SourceTV camera is now controlled by %s.", pPlayer->GetPlayerName() ); UTIL_ClientPrintFilter( filter, HUD_PRINTTALK, szText ); } else { // tell all spectators that the camera is avaliable again. UTIL_ClientPrintFilter( filter, HUD_PRINTTALK, "SourceTV camera switched to auto-director mode." ); } return true; }
void CHL2MP_Player::DeathSound( const CTakeDamageInfo &info ) { if ( m_hRagdoll && m_hRagdoll->GetBaseAnimating()->IsDissolving() ) return; char szStepSound[128]; Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.Die", GetPlayerModelSoundPrefix() ); const char *pModelName = STRING( GetModelName() ); CSoundParameters params; if ( GetParametersForSound( szStepSound, params, pModelName ) == false ) return; Vector vecOrigin = GetAbsOrigin(); CRecipientFilter filter; filter.AddRecipientsByPAS( vecOrigin ); EmitSound_t ep; ep.m_nChannel = params.channel; ep.m_pSoundName = params.soundname; ep.m_flVolume = params.volume; ep.m_SoundLevel = params.soundlevel; ep.m_nFlags = 0; ep.m_nPitch = params.pitch; ep.m_pOrigin = &vecOrigin; EmitSound( filter, entindex(), ep ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWarsWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) { #if 0 const char* tracer = "ASWUTracer"; //if (GetActiveASWWeapon()) // tracer = GetActiveASWWeapon()->GetUTracerType(); #ifdef CLIENT_DLL CEffectData data; data.m_vOrigin = tr.endpos; data.m_hEntity = this; //data.m_nMaterial = m_iDamageAttributeEffects; DispatchEffect( tracer, data ); #else CRecipientFilter filter; filter.AddAllPlayers(); if (gpGlobals->maxClients > 1 && GetCommander()) { filter.RemoveRecipient(GetCommander()); } UserMessageBegin( filter, tracer ); WRITE_SHORT( entindex() ); WRITE_FLOAT( tr.endpos.x ); WRITE_FLOAT( tr.endpos.y ); WRITE_FLOAT( tr.endpos.z ); //WRITE_SHORT( m_iDamageAttributeEffects ); MessageEnd(); #endif #else #ifdef CLIENT_DLL ASWUTracer( GetOwner(), tr.endpos, m_vTracerColor ); #endif #endif // 0 }
//----------------------------------------------------------------------------- // Purpose: // Input : origin - // *soundname - //----------------------------------------------------------------------------- void CMoveHelperServer::StartSound( const Vector& origin, const char *soundname ) { //MDB - Changing this to send to PAS, as the overloaded function below has done. //Also removed the UsePredictionRules, client does not yet play the equivalent sound CRecipientFilter filter; filter.AddRecipientsByPAS( origin ); CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), soundname ); }
//----------------------------------------------------------------------------- // Purpose: // Input : step - // fvol - // force - force sound to play //----------------------------------------------------------------------------- void CDODPlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) { if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) return; #if defined( CLIENT_DLL ) // during prediction play footstep sounds only once if ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) return; #endif if ( !psurface ) return; unsigned short stepSoundName = m_Local.m_nStepside ? psurface->sounds.stepleft : psurface->sounds.stepright; m_Local.m_nStepside = !m_Local.m_nStepside; if ( !stepSoundName ) return; IPhysicsSurfaceProps *physprops = MoveHelper( )->GetSurfaceProps(); const char *pSoundName = physprops->GetString( stepSoundName ); CSoundParameters params; // we don't always know the model, so go by team char *pModelNameForGender = DOD_PLAYERMODEL_AXIS_RIFLEMAN; if( GetTeamNumber() == TEAM_ALLIES ) pModelNameForGender = DOD_PLAYERMODEL_US_RIFLEMAN; if ( !CBaseEntity::GetParametersForSound( pSoundName, params, pModelNameForGender ) ) return; CRecipientFilter filter; filter.AddRecipientsByPAS( vecOrigin ); #ifndef CLIENT_DLL // im MP, server removed all players in origins PVS, these players // generate the footsteps clientside if ( gpGlobals->maxClients > 1 ) filter.RemoveRecipientsByPVS( vecOrigin ); #endif EmitSound_t ep; ep.m_nChannel = params.channel; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nFlags = 0; ep.m_nPitch = params.pitch; ep.m_pOrigin = &vecOrigin; EmitSound( filter, entindex(), ep ); }
void EmitAmbientSound( int entindex, const Vector& origin, const char *soundname, float flVolume, int iFlags, int iPitch, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) { // Pull data from parameters CSoundParameters params; if ( !soundemitterbase->GetParametersForSound( soundname, params, GENDER_NONE ) ) { return; } if( iFlags & SND_CHANGE_PITCH ) { params.pitch = iPitch; } if( iFlags & SND_CHANGE_VOL ) { params.volume = flVolume; } #if defined( CLIENT_DLL ) enginesound->EmitAmbientSound( params.soundname, params.volume, params.pitch, iFlags, soundtime ); #else engine->EmitAmbientSound(entindex, origin, params.soundname, params.volume, params.soundlevel, iFlags, params.pitch, soundtime ); #endif bool needsCC = !( iFlags & ( SND_STOP | SND_CHANGE_VOL | SND_CHANGE_PITCH ) ); float soundduration = 0.0f; if ( duration || needsCC ) { soundduration = enginesound->GetSoundDuration( params.soundname ); if ( duration ) { *duration = soundduration; } } TraceEmitSound( "EmitAmbientSound: '%s' emitted as '%s' (ent %i)\n", soundname, params.soundname, entindex ); // We only want to trigger the CC on the start of the sound, not on any changes or halting of the sound if ( needsCC ) { CRecipientFilter filter; filter.AddAllPlayers(); filter.MakeReliable(); CUtlVector< Vector > dummy; EmitCloseCaption( filter, entindex, false, soundname, dummy, soundduration, false ); } }
void EmitCloseCaption( IRecipientFilter& filter, int entindex, const CSoundParameters & params, const EmitSound_t & ep ) { // No close captions in multiplayer... if ( gpGlobals->maxClients > 1 || (gpGlobals->maxClients==1 && !g_pClosecaption->GetBool())) { return; } if ( !ep.m_bEmitCloseCaption ) { return; } // 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 ); // Anyone left? if ( filterCopy.GetRecipientCount() <= 0 ) { return; } float duration = 0.0f; if ( ep.m_pflSoundDuration ) { duration = *ep.m_pflSoundDuration; } else { duration = enginesound->GetSoundDuration( params.soundname ); } bool fromplayer = false; CBaseEntity *ent = CBaseEntity::Instance( entindex ); if ( ent ) { while ( ent ) { if ( ent->IsPlayer() ) { fromplayer = true; break; } ent = ent->GetOwnerEntity(); } } EmitCloseCaption( filter, entindex, fromplayer, ep.m_pSoundName, ep.m_UtlVecSoundOrigin, duration, ep.m_bWarnOnMissingCloseCaption ); }
// if we've already started showing the credits and another player has joined up, show him them too void CASW_Intro_Control::PlayerSpawned(CASW_Player *pPlayer) { Msg("CASW_Intro_Control::PlayerSpawned, showncredits = %d\n", m_bShownCredits); if (m_bShownCredits && pPlayer) { Msg("Sending user message to this player telling him to show the credits\n"); CRecipientFilter filter; filter.AddRecipient(pPlayer); UserMessageBegin( filter, "LaunchCredits" ); MessageEnd(); } }
int DotaObjective::OnTakeDamage( const CTakeDamageInfo &inputInfo ) { if ( m_bMet ) return 0; if ( !(inputInfo.GetDamageType() & DMG_BULLET) ) { CHL2MP_Player * playerAttacker = ToHL2MPPlayer( inputInfo.GetAttacker() ); CreepMaker * maker = (CreepMaker*)gEntList.FindEntityByName( NULL, m_creepMakerName ); if ( !maker ) AssertMsg( false, "Objective can't find its creepmaker!\n" ); CAI_BaseNPC * guardian = (CAI_BaseNPC*)gEntList.FindEntityByName( NULL, m_guardianName ); if( guardian && guardian->IsAlive() ) { if( playerAttacker ) ClientPrint( playerAttacker, HUD_PRINTTALK, UTIL_VarArgs("The guradian is alive in this lane, you can't hurt the gate.\n") ); } else { m_timesHit++; m_timesHit = min(m_timesHit, OBJECTIVE_HEALTHI); // make sure times hit never goes above the maximum times an objective can be hit! CRecipientFilter user; user.AddRecipientsByTeam( this->GetTeam() ); user.MakeReliable(); char szText[200]; Q_snprintf( szText, sizeof(szText), "Your ally gate is under attack from an enemy!" ); UTIL_ClientPrintFilter( user, HUD_PRINTCENTER, szText ); if( playerAttacker ) ClientPrint( playerAttacker, HUD_PRINTTALK, UTIL_VarArgs("Gate has %i health left.\n", OBJECTIVE_HEALTHI - m_timesHit) ); if (m_timesHit >= OBJECTIVE_HEALTHI) { TakeAction(DOBJ_ACTION_CLOSE); } else { IGameEvent *pEvent = gameeventmanager->CreateEvent( "objectivegate_attacked" ); if ( pEvent ) { pEvent->SetString( "lane", GetLane() ); pEvent->SetInt( "team", this->GetTeamNumber() ); pEvent->SetFloat( "health", (OBJECTIVE_HEALTHF - m_timesHit)/OBJECTIVE_HEALTHF ); gameeventmanager->FireEvent( pEvent ); } } } } return 0; }
//----------------------------------------------------------------------------- // Purpose: // Input : step - // fvol - // force - force sound to play //----------------------------------------------------------------------------- void CHL2MP_Player::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) { if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) return; #if defined( CLIENT_DLL ) // during prediction play footstep sounds only once if ( !prediction->IsFirstTimePredicted() ) return; #endif if ( GetFlags() & FL_DUCKING ) return; m_Local.m_nStepside = !m_Local.m_nStepside; char szStepSound[128]; if ( m_Local.m_nStepside ) { Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); } else { Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); } CSoundParameters params; if ( GetParametersForSound( szStepSound, params, NULL ) == false ) return; CRecipientFilter filter; filter.AddRecipientsByPAS( vecOrigin ); #ifndef CLIENT_DLL // im MP, server removed all players in origins PVS, these players // generate the footsteps clientside if ( gpGlobals->maxClients > 1 ) filter.RemoveRecipientsByPVS( vecOrigin ); #endif EmitSound_t ep; ep.m_nChannel = CHAN_BODY; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nFlags = 0; ep.m_nPitch = params.pitch; ep.m_pOrigin = &vecOrigin; EmitSound( filter, entindex(), ep ); }
//----------------------------------------------------------------------------- // Purpose: // Input : step - // fvol - // force - force sound to play //----------------------------------------------------------------------------- void CHL2MP_Player::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) { if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) return; #if defined( CLIENT_DLL ) // during prediction play footstep sounds only once if ( !prediction->IsFirstTimePredicted() ) return; #endif if ( GetFlags() & FL_DUCKING ) return; int nSide = m_Local.m_nStepside; m_Local.m_nStepside = !m_Local.m_nStepside; unsigned short stepSoundName = nSide ? psurface->sounds.stepleft : psurface->sounds.stepright; IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); const char *pSoundName = physprops->GetString( stepSoundName ); CSoundParameters params; if ( GetParametersForSound( pSoundName, params, NULL ) == false ) return; CRecipientFilter filter; filter.AddRecipientsByPAS( vecOrigin ); #ifndef CLIENT_DLL // im MP, server removed all players in origins PVS, these players // generate the footsteps clientside if ( gpGlobals->maxClients > 1 ) filter.RemoveRecipientsByPVS( vecOrigin ); #endif EmitSound_t ep; ep.m_nChannel = CHAN_BODY; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nFlags = 0; ep.m_nPitch = params.pitch; ep.m_pOrigin = &vecOrigin; EmitSound( filter, entindex(), ep ); }
//----------------------------------------------------------------------------- // Purpose: Returning true means don't even call TE func // Input : filter - // *suppress_host - // Output : static bool //----------------------------------------------------------------------------- bool SuppressTE( CRecipientFilter& filter ) { if ( GetSuppressHost() ) { if ( !filter.IgnorePredictionCull() ) { filter.RemoveRecipient( (CBasePlayer *)GetSuppressHost() ); } if ( !filter.GetRecipientCount() ) { // Suppress it return true; } } // There's at least one recipient return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTeam::AwardAchievement( int iAchievement ) { Assert( iAchievement >= 0 && iAchievement < 255 ); // must fit in short CRecipientFilter filter; int iNumPlayers = GetNumPlayers(); for ( int i=0;i<iNumPlayers;i++ ) { if ( GetPlayer(i) ) { filter.AddRecipient( GetPlayer(i) ); } } UserMessageBegin( filter, "AchievementEvent" ); WRITE_SHORT( iAchievement ); MessageEnd(); }
void CDODPlayer::CheckProneMoveSound( int groundspeed, bool onground ) { #ifdef CLIENT_DLL bool bShouldPlay = (groundspeed > 10) && (onground == true) && m_Shared.IsProne() && IsAlive(); if ( m_bPlayingProneMoveSound && !bShouldPlay ) { StopSound( "Player.MoveProne" ); m_bPlayingProneMoveSound= false; } else if ( !m_bPlayingProneMoveSound && bShouldPlay ) { CRecipientFilter filter; filter.AddRecipientsByPAS( WorldSpaceCenter() ); EmitSound( filter, entindex(), "Player.MoveProne" ); m_bPlayingProneMoveSound = true; } #endif }
//----------------------------------------------------------------------------- // plays a sound //----------------------------------------------------------------------------- void CMoveHelperServer::StartSound( const Vector& origin, int channel, char const* sample, float volume, soundlevel_t soundlevel, int fFlags, int pitch ) { CRecipientFilter filter; filter.AddRecipientsByPAS( origin ); // FIXME, these sounds should not go to the host entity ( SND_NOTHOST ) if ( gpGlobals->maxClients == 1 ) { // Always send sounds down in SP EmitSound_t ep; ep.m_nChannel = channel; ep.m_pSoundName = sample; ep.m_flVolume = volume; ep.m_SoundLevel = soundlevel; ep.m_nFlags = fFlags; ep.m_nPitch = pitch; ep.m_pOrigin = &origin; CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), ep ); } else { filter.UsePredictionRules(); EmitSound_t ep; ep.m_nChannel = channel; ep.m_pSoundName = sample; ep.m_flVolume = volume; ep.m_SoundLevel = soundlevel; ep.m_nFlags = fFlags; ep.m_nPitch = pitch; ep.m_pOrigin = &origin; CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), ep ); } }
void CPortalGameMovement::PlayerRoughLandingEffects( float fvol ) { BaseClass::PlayerRoughLandingEffects( fvol ); #ifndef CLIENT_DLL if ( fvol >= 1.0 ) { // Play the future shoes sound CRecipientFilter filter; filter.AddRecipientsByPAS( player->GetAbsOrigin() ); CSoundParameters params; if ( CBaseEntity::GetParametersForSound( "PortalPlayer.FallRecover", params, NULL ) ) { EmitSound_t ep( params ); ep.m_nPitch = 125.0f - player->m_Local.m_flFallVelocity * 0.03f; // lower pitch the harder they land ep.m_flVolume = MIN( player->m_Local.m_flFallVelocity * 0.00075f - 0.38, 1.0f ); // louder the harder they land CBaseEntity::EmitSound( filter, player->entindex(), ep ); } } #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : src - //----------------------------------------------------------------------------- void CRecipientFilter::CopyFrom( const CRecipientFilter& src ) { m_bReliable = src.IsReliable(); m_bInitMessage = src.IsInitMessage(); m_bUsingPredictionRules = src.IsUsingPredictionRules(); m_bIgnorePredictionCull = src.IgnorePredictionCull(); int c = src.GetRecipientCount(); for ( int i = 0; i < c; ++i ) { m_Recipients.AddToTail( src.GetRecipientIndex( i ) ); } }
void ClientPrintFilter(CBasePlayer *pPlayer, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) { CRecipientFilter filter; filter.AddRecipient( pPlayer ); UTIL_ClientPrintFilter(filter, msg_dest, msg_name, param1, param2, param3, param4); }
//----------------------------------------------------------------------------- // Purpose: // Input : step - // fvol - // force - force sound to play //----------------------------------------------------------------------------- void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) { if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) return; #if defined( CLIENT_DLL ) // during prediction play footstep sounds only once if ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) return; #endif if ( !psurface ) return; int nSide = m_Local.m_nStepside; unsigned short stepSoundName = nSide ? psurface->sounds.stepleft : psurface->sounds.stepright; if ( !stepSoundName ) return; m_Local.m_nStepside = !nSide; CSoundParameters params; Assert( nSide == 0 || nSide == 1 ); if ( m_StepSoundCache[ nSide ].m_usSoundNameIndex == stepSoundName ) { params = m_StepSoundCache[ nSide ].m_SoundParameters; } else { IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); const char *pSoundName = physprops->GetString( stepSoundName ); if ( !CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) ) return; // Only cache if there's one option. Otherwise we'd never here any other sounds if ( params.count == 1 ) { m_StepSoundCache[ nSide ].m_usSoundNameIndex = stepSoundName; m_StepSoundCache[ nSide ].m_SoundParameters = params; } } CRecipientFilter filter; filter.AddRecipientsByPAS( vecOrigin ); #ifndef CLIENT_DLL // in MP, server removes all players in the vecOrigin's PVS, these players generate the footsteps client side if ( gpGlobals->maxClients > 1 ) { filter.RemoveRecipientsByPVS( vecOrigin ); } #endif EmitSound_t ep; ep.m_nChannel = CHAN_BODY; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nFlags = 0; ep.m_nPitch = params.pitch; ep.m_pOrigin = &vecOrigin; EmitSound( filter, entindex(), ep ); }
VoiceCommandMenuItem_t *CMultiplayRules::VoiceCommand( CBaseMultiplayerPlayer *pPlayer, int iMenu, int iItem ) { // have the player speak the concept that is in a particular menu slot if ( !pPlayer ) return NULL; if ( iMenu < 0 || iMenu >= m_VoiceCommandMenus.Count() ) return NULL; if ( iItem < 0 || iItem >= m_VoiceCommandMenus.Element( iMenu ).Count() ) return NULL; VoiceCommandMenuItem_t *pItem = &m_VoiceCommandMenus.Element( iMenu ).Element( iItem ); Assert( pItem ); char szResponse[AI_Response::MAX_RESPONSE_NAME]; if ( pPlayer->CanSpeakVoiceCommand() ) { CMultiplayer_Expresser *pExpresser = pPlayer->GetMultiplayerExpresser(); Assert( pExpresser ); pExpresser->AllowMultipleScenes(); if ( pPlayer->SpeakConceptIfAllowed( pItem->m_iConcept, NULL, szResponse, AI_Response::MAX_RESPONSE_NAME ) ) { // show a subtitle if we need to if ( pItem->m_bShowSubtitle ) { CRecipientFilter filter; if ( pItem->m_bDistanceBasedSubtitle ) { filter.AddRecipientsByPAS( pPlayer->WorldSpaceCenter() ); // further reduce the range to a certain radius int i; for ( i = filter.GetRecipientCount()-1; i >= 0; i-- ) { int index = filter.GetRecipientIndex(i); CBasePlayer *pListener = UTIL_PlayerByIndex( index ); if ( pListener && pListener != pPlayer ) { float flDist = ( pListener->WorldSpaceCenter() - pPlayer->WorldSpaceCenter() ).Length2D(); if ( flDist > VOICE_COMMAND_MAX_SUBTITLE_DIST ) filter.RemoveRecipientByPlayerIndex( index ); } } } else { filter.AddAllPlayers(); } // if we aren't a disguised spy if ( !pPlayer->ShouldShowVoiceSubtitleToEnemy() ) { // remove players on other teams filter.RemoveRecipientsNotOnTeam( pPlayer->GetTeam() ); } // Register this event in the mod-specific usermessages .cpp file if you hit this assert Assert( usermessages->LookupUserMessage( "VoiceSubtitle" ) != -1 ); // Send a subtitle to anyone in the PAS UserMessageBegin( filter, "VoiceSubtitle" ); WRITE_BYTE( pPlayer->entindex() ); WRITE_BYTE( iMenu ); WRITE_BYTE( iItem ); MessageEnd(); } pPlayer->NoteSpokeVoiceCommand( szResponse ); } else { pItem = NULL; } pExpresser->DisallowMultipleScenes(); return pItem; } return NULL; }
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 } }