//-----------------------------------------------------------------------------
// Purpose: Given and activity ID, return the activity name
//-----------------------------------------------------------------------------
const char *CAI_BaseNPC::GetActivityName(int actID) 
{
	Assert( m_pActivitySR );
	if ( !m_pActivitySR )
		return "!!INVALID!!";

	const char *name = m_pActivitySR->GetStringText(actID);	

	if( !name )
	{
		AssertOnce( !"CAI_BaseNPC::GetActivityName() returning NULL!" );
	}

	return name;
}
Example #2
0
// FIXME: Figure out a better way to do this?
//-----------------------------------------------------------------------------
int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI )
{
 	s_pShaderAPI = pShaderAPI;

	int mod = 0;
	if( UsingFlashlight(params) )
	{
		mod |= SHADER_USING_FLASHLIGHT;
	}
	
	if ( UsingEditor(params) )
	{
		mod |= SHADER_USING_EDITOR;
	}

	if( IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ) )
	{
		AssertOnce( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) );
		if( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) )
		{
			mod |= SHADER_USING_FIXED_FUNCTION_BAKED_LIGHTING;
		}
	}

	if ( IsSnapshotting() )
	{
		if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) )
			mod |= SHADER_USING_GBUFFER0;
		if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) )
			mod |= SHADER_USING_GBUFFER1;
	}
	else
	{
		int nFixedLightingMode = pShaderAPI->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
		if ( nFixedLightingMode & 1 )
			mod |= SHADER_USING_GBUFFER0;
		if ( nFixedLightingMode & 2 )
			mod |= SHADER_USING_GBUFFER1;
	}
	s_pShaderAPI = NULL;
	return mod;
}
Ep2LevelStats_t::WeaponLump_t *CEP2GameStats::FindWeaponsLump( char const *pchWeaponName, bool bPrimary )
{
	if ( !m_pCurrentMap )
		return NULL;

	if ( !pchWeaponName )
	{
		AssertOnce( !"FindWeaponsLump pchWeaponName == NULL" );
		return NULL;
	}

	char lookup[ 512 ];
	Q_snprintf( lookup, sizeof( lookup ), "%s_%s", pchWeaponName, bPrimary ? "primary" : "secondary" );
	int idx = m_pCurrentMap->m_dictWeapons.Find( lookup );
	if ( idx == m_pCurrentMap->m_dictWeapons.InvalidIndex() )
	{
		idx = m_pCurrentMap->m_dictWeapons.Insert( lookup );
	}

	return &m_pCurrentMap->m_dictWeapons[ idx ];
}
Example #4
0
//-----------------------------------------------------------------------------
// FIXME: Figure out a better way to do this?
//-----------------------------------------------------------------------------
int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI )
{
 	s_pShaderAPI = pShaderAPI;

	int mod = 0;
	if ( GetAlpha(params) < 1.0f )
	{
		mod |= SHADER_USING_ALPHA_MODULATION;
	}

	float color[3];
	params[COLOR]->GetVecValue( color, 3 );
	if ((color[0] < 1.0) || (color[1] < 1.0) || (color[2] < 1.0))
	{
		mod |= SHADER_USING_COLOR_MODULATION;
	}

	if( UsingFlashlight(params) )
	{
		mod |= SHADER_USING_FLASHLIGHT;
	}
	
	if ( UsingEditor(params) )
	{
		mod |= SHADER_USING_EDITOR;
	}

	if( IS_FLAG2_SET( MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING ) )
	{
		AssertOnce( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) );
		if( IS_FLAG2_SET( MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS ) )
		{
			mod |= SHADER_USING_FIXED_FUNCTION_BAKED_LIGHTING;
		}
	}

	s_pShaderAPI = NULL;

	return mod;
}
// Load a static copy buffer (g_temppaintbuffer) with the requested number of samples, 
// with the first sample(s) in the buffer always set up as the last sample(s) of the previous load.
// Return a pointer to the head of the copy buffer.
// This ensures that interpolating pitch shifters always have the previous sample to reference.
//		pChannel:				sound's channel data
//		sample_load_request:	number of samples to load from source data
//		pSamplesLoaded:			returns the actual number of samples loaded (should always = sample_load_request)
//		copyBuf:				req'd by GetOutputData, used by some Mixers
// Returns: NULL ptr to data if no samples available, otherwise always fills remainder of copy buffer with
// 0 to pad remainder.
// NOTE: DO NOT MODIFY THIS ROUTINE (KELLYB)
char *CAudioMixerWave::LoadMixBuffer( channel_t *pChannel, int sample_load_request, int *pSamplesLoaded, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
{
	int samples_loaded;
	char *pSample = NULL;
	char *pData = NULL;
	int cCopySamps = 0;

	// save index of last sample loaded (updated in GetOutputData)
	int sample_loaded_index = m_sample_loaded_index;

	// get data from source (copyBuf is expected to be available for use)
	samples_loaded = GetOutputData( (void **)&pData, sample_load_request, copyBuf );
	if ( !samples_loaded && sample_load_request )
	{
		// none available, bail out
		// 360 might not be able to get samples due to latency of loop seek
		// could also be the valid EOF for non-loops (caller keeps polling for data, until no more)
		AssertOnce( IsX360() || !m_pData->Source().IsLooped() );
		*pSamplesLoaded = 0;
		return NULL;
	}

	int samplesize = GetMixSampleSize();
	char *pCopy = (char *)g_temppaintbuffer;

	if ( IsX360() || IsDebug() )
	{	
		// for safety, 360 always validates sample request, due to new xma audio code and possible logic flaws
		// PC can expect number of requested samples to be within tolerances due to exisiting aged code
		// otherwise buffer overruns cause hard to track random crashes
		if ( ( ( sample_load_request + 1 ) * samplesize ) > ( TEMP_COPY_BUFFER_SIZE * sizeof( portable_samplepair_t ) ) )
		{
			// make sure requested samples will fit in temp buffer.
			// if this assert fails, then pitch is too high (ie: > 2.0) or the sample counters have diverged.
			// NOTE: to prevent this, pitch should always be capped in MixDataToDevice (but isn't nor are the sample counters).
			DevWarning( "LoadMixBuffer: sample load request %d exceeds buffer sizes\n", sample_load_request );
			Assert( 0 );
			*pSamplesLoaded = 0;
			return NULL;
		}
	}

	// copy all samples from pData to copy buffer, set 0th sample to saved previous sample - this ensures
	// interpolation pitch shift routines always have a previous sample to reference.

	// copy previous sample(s) to head of copy buffer pCopy
	// In some cases, we'll need the previous 2 samples.  This occurs when
	// Rate < 1.0 - in example below, sample 4.86 - 6.48 requires samples 4-7 (previous samples saved are 4 & 5)

	/*
	Example:
		rate = 0.81, sampleCount = 3 (ie: # of samples to return )

		_____load 3______       ____load 3_______       __load 2__

		0		1		 2		 3		 4		 5		6		7		sample_index     (whole samples)

		^     ^      ^      ^      ^     ^     ^     ^     ^        
		|     |      |      |      |     |     |     |     |   
		0    0.81   1.68   2.43   3.24  4.05  4.86  5.67  6.48          m_fsample_index  (rate*sample)
		_______________    ________________   ________________
						^   ^                  ^ ^        	
						|   |                  | |                                    
	m_sample_loaded_index   |                  | m_sample_loaded_index
							|                  |
		m_fsample_index----   		       ----m_fsample_index

		[return 3 samp]     [return 3 samp]    [return 3 samp]
	*/
	pSample = &(pChannel->sample_prev[0]);

	// determine how many saved samples we need to copy to head of copy buffer (0,1 or 2)
	// so that pitch interpolation will correctly reference samples.
	// NOTE: pitch interpolators always reference the sample before and after the indexed sample.

	// cCopySamps = sample_max_loaded - floor(m_fsample_index);

	if ( sample_loaded_index < 0 || (floor(m_fsample_index) > sample_loaded_index))
	{
		// no samples previously loaded, or
		// next sample index is entirely within the next block of samples to be loaded,
		// so we won't need any samples from the previous block. (can occur when rate > 2.0)
		cCopySamps = 0;
	}
	else if ( m_fsample_index < sample_loaded_index )
	{
		// next sample index is entirely within the previous block of samples loaded,
		// so we'll need the last 2 samples loaded.  (can occur when rate < 1.0)		
		Assert ( ceil(m_fsample_index + 0.00000001) == sample_loaded_index );
		cCopySamps = 2;
	}
	else
	{
		// next sample index is between the next block and the previously loaded block,
		// so we'll need the last sample loaded.  (can occur when 1.0 < rate < 2.0)
		Assert( floor(m_fsample_index) == sample_loaded_index );
		cCopySamps = 1;
	}
	Assert( cCopySamps >= 0 && cCopySamps <= 2 );

	// point to the sample(s) we are to copy
	if ( cCopySamps )
	{
		pSample = cCopySamps == 1 ? pSample + samplesize : pSample;
		Q_memcpy( pCopy, pSample, samplesize * cCopySamps );
		pCopy += samplesize * cCopySamps;
	}

	// don't overflow copy buffer
	Assert ( (PAINTBUFFER_MEM_SIZE * sizeof( portable_samplepair_t )) > ( ( samples_loaded + 1 ) * samplesize ) );
	
	// copy loaded samples from pData into pCopy
	// and update pointer to free space in copy buffer
	if ( ( samples_loaded * samplesize ) != 0 && !pData )
	{
		char const *pWavName = "";
		CSfxTable *source = pChannel->sfx;
		if ( source )
		{
			pWavName = source->getname();
		}
		
		Warning( "CAudioMixerWave::LoadMixBuffer: '%s' samples_loaded * samplesize = %i but pData == NULL\n", pWavName, ( samples_loaded * samplesize ) );
		*pSamplesLoaded = 0;
		return NULL;
	}

	Q_memcpy( pCopy, pData, samples_loaded * samplesize );
	pCopy += samples_loaded * samplesize;
	
	// if we loaded fewer samples than we wanted to, and we're not
	// delaying, load more samples or, if we run out of samples from non-looping source, 
	// pad copy buffer.
	if ( samples_loaded < sample_load_request )
	{
		// retry loading source data until 0 bytes returned, or we've loaded enough data.
		// if we hit 0 bytes, fill remaining space in copy buffer with 0 and exit
		int samples_load_extra;
		int samples_loaded_retry = -1;
			
		for ( int k = 0; (k < 10000 && samples_loaded_retry && samples_loaded < sample_load_request); k++ )
		{
			// how many more samples do we need to satisfy load request
			samples_load_extra = sample_load_request - samples_loaded;
			samples_loaded_retry = GetOutputData( (void**)&pData, samples_load_extra, copyBuf );

			// copy loaded samples from pData into pCopy
			if ( samples_loaded_retry )
			{
				if ( ( samples_loaded_retry * samplesize ) != 0 && !pData )
				{
					Warning( "CAudioMixerWave::LoadMixBuffer:  samples_loaded_retry * samplesize = %i but pData == NULL\n", ( samples_loaded_retry * samplesize ) );
					*pSamplesLoaded = 0;
					return NULL;
				}

				Q_memcpy( pCopy, pData, samples_loaded_retry * samplesize );
				pCopy += samples_loaded_retry * samplesize;
				samples_loaded += samples_loaded_retry;
			}
		}
	}

	// if we still couldn't load the requested samples, fill rest of copy buffer with 0
	if ( samples_loaded < sample_load_request )
	{
		// should always be able to get as many samples as we request from looping sound sources
		AssertOnce ( IsX360() || !m_pData->Source().IsLooped() );

		// these samples are filled with 0, not loaded.
		// non-looping source hit end of data, fill rest of g_temppaintbuffer with 0
		int samples_zero_fill = sample_load_request - samples_loaded;

		Q_memset( pCopy, 0, samples_zero_fill * samplesize );
		pCopy += samples_zero_fill * samplesize;
		samples_loaded += samples_zero_fill;
	}

	if ( samples_loaded >= 2 )
	{
		// always save last 2 samples from copy buffer to channel 
		// (we'll need 0,1 or 2 samples as start of next buffer for interpolation)
		Assert( sizeof( pChannel->sample_prev ) >= samplesize*2 );
		pSample = pCopy - samplesize*2;
		Q_memcpy( &(pChannel->sample_prev[0]), pSample, samplesize*2 );
	}

	// this routine must always return as many samples loaded (or zeros) as requested.
	Assert( samples_loaded == sample_load_request );

	*pSamplesLoaded = samples_loaded;

	return (char *)g_temppaintbuffer;
}
void CLocalNetworkBackdoor::EndEntityStateUpdate()
{
	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_START );

	// Handle entities created.
	int i;
	for ( i=0; i < m_nEntsCreated; i++ )
	{
		MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

		int iEdict = m_EntsCreatedIndices[i];
		CCachedEntState *pCached = &m_CachedEntState[iEdict];
		IClientNetworkable *pNet = pCached->m_pNetworkable;

		pNet->PostDataUpdate( DATA_UPDATE_CREATED );
		pNet->NotifyShouldTransmit( SHOULDTRANSMIT_START );
		pCached->m_bDormant = false;
	}

	// Handle entities changed.
	for ( i=0; i < m_nEntsChanged; i++ )
	{
		MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

		int iEdict = m_EntsChangedIndices[i];
		m_CachedEntState[iEdict].m_pNetworkable->PostDataUpdate( DATA_UPDATE_DATATABLE_CHANGED );
	}

	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_END );

	// Handle entities removed (= SV_WriteDeletions() in normal mode)
	int nDWords = m_PrevEntsAlive.GetNumDWords();

	// Handle entities removed.
	for ( i=0; i < nDWords; i++ )
	{
		unsigned long prevEntsAlive = m_PrevEntsAlive.GetDWord( i );
		unsigned long entsAlive = m_EntsAlive.GetDWord( i );
		unsigned long toDelete = (prevEntsAlive ^ entsAlive) & prevEntsAlive;

		if ( toDelete )
		{
			for ( int iBit=0; iBit < 32; iBit++ )
			{
				if ( toDelete & (1 << iBit) )
				{
					int iEdict = (i<<5) + iBit;
					if ( iEdict < MAX_EDICTS )
					{
						if ( m_CachedEntState[iEdict].m_pNetworkable )
						{
							m_CachedEntState[iEdict].m_pNetworkable->Release();
							m_CachedEntState[iEdict].m_pNetworkable = NULL;
						}
						else
						{
							AssertOnce( !"EndEntityStateUpdate:  Would have crashed with NULL m_pNetworkable\n" );
						}
					}
					else
					{
						AssertOnce( !"EndEntityStateUpdate:  Would have crashed with entity out of range\n" );
					}
				}
			}
		}
	}

	// Remember the previous state of which entities were around.
	m_PrevEntsAlive = m_EntsAlive;

	// end of all entity update activity
	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_END );

	/*
	#ifdef _DEBUG
	for ( i=0; i <= highest_index; i++ )
	{
	if ( !( m_EntsAlive[i>>5] & (1 << (i & 31)) ) )
	Assert( !m_CachedEntState[i].m_pNetworkable );

	if ( ( m_EntsAlive[i>>5] & (1 << (i & 31)) ) &&
	( m_EntsCreated[i>>5] & (1 << (i & 31)) ) )
	{
	Assert( FindInList( m_EntsCreatedIndices, m_nEntsCreated, i ) );
	}

	if ( (m_EntsAlive[i>>5] & (1 << (i & 31))) && 
	!(m_EntsCreated[i>>5] & (1 << (i & 31))) &&
	(m_EntsChanged[i>>5] & (1 << (i & 31)))
	)
	{
	Assert( FindInList( m_EntsChangedIndices, m_nEntsChanged, i ) );
	}
	}
	#endif
	*/
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing )
{

	ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint];

	if ( pEffect->pParticleEffect->m_pDef->IsScreenSpaceEffect() && iPoint == 0 )
	{
		pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) );
		pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vec3_origin );
		return;
	}

	if ( !pPoint->hEntity.Get() )
	{
		if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing )
		{
			pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) );
			pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset );
			pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset );
		}

		pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL );
		return;
	}

	// Only update non-follow particles when we're initializing, 
	if ( !bInitializing && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) )
		return;

	if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN )
		return;

	Vector vecOrigin, vecForward, vecRight, vecUp;

	switch ( pPoint->iAttachType )
	{
	case PATTACH_POINT:
	case PATTACH_POINT_FOLLOW:
		{
			C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();

			bool bValid = false;
			Assert( pAnimating );
			if ( pAnimating )
			{
				matrix3x4_t attachmentToWorld;

				if ( pAnimating->IsViewModel() )
				{
					C_BasePlayer *pPlayer = ToBasePlayer( ((C_BaseViewModel *)pAnimating)->GetOwner() );
					ACTIVE_SPLITSCREEN_PLAYER_GUARD( C_BasePlayer::GetSplitScreenSlotForPlayer( pPlayer ) );

					if ( pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
					{
						bValid = true;
						MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp );
						MatrixPosition( attachmentToWorld, vecOrigin );

						if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() )
						{
							FormatViewModelAttachment( pPlayer, vecOrigin, true );
						}
					}
				}
				else
				{
					// HACK_GETLOCALPLAYER_GUARD( "CParticleProperty::UpdateControlPoint" );

					if ( pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
					{
						bValid = true;
						MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp );
#ifdef _DEBUG
						float flTests[3] = {vecForward.Dot( vecRight ), vecRight.Dot( vecUp ), vecUp.Dot( vecForward )};
						static float s_flMaxTest = 0.001f;
						Assert( fabs( flTests[0] ) + fabs( flTests[1] ) + fabs( flTests[2] ) < s_flMaxTest );
#endif
						MatrixPosition( attachmentToWorld, vecOrigin );

						if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() )
						{
							HACK_GETLOCALPLAYER_GUARD( "CParticleProperty::UpdateControlPoint" );

							FormatViewModelAttachment( NULL, vecOrigin, true );
						}
					}
				}
			}

			if ( !bValid )
			{
				static bool bWarned = false;
				if ( !bWarned )
				{
					bWarned = true;
					DevWarning( "Attempted to attach particle effect %s to an unknown attachment on entity %s\n",
						pEffect->pParticleEffect->m_pDef->GetName(), pAnimating->GetClassname() );
				}
			}
			if ( !bValid )
			{
				AssertOnce( 0 );
				return;
			}
		}
		break;

	case PATTACH_ABSORIGIN:
	case PATTACH_ABSORIGIN_FOLLOW:
	default:
		{
			vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset;
			pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp );
		}
		break;

	case PATTACH_EYES_FOLLOW:
		{
			C_BaseEntity *pEnt = pPoint->hEntity;

			if ( !pEnt->IsPlayer() )
				return;

			C_BasePlayer *pPlayer = assert_cast< C_BasePlayer* >( pEnt );

			bool bValid = false;
			Assert( pPlayer );
			if ( pPlayer )
			{
				bValid = true;
				vecOrigin = pPlayer->EyePosition() + pPoint->vecOriginOffset;
				pPlayer->EyeVectors( &vecForward, &vecRight, &vecUp );
			}
			if ( !bValid )
			{
				AssertOnce( 0 );
				return;
			}
		}
		break;

	case PATTACH_CUSTOMORIGIN_FOLLOW:
		{
			matrix3x4_t mat;
			MatrixMultiply( pPoint->hEntity->RenderableToWorldTransform(), pPoint->matOffset, mat );
			MatrixVectors( mat, &vecForward, &vecRight, &vecUp );
			vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset;
		}
		break;
	}
	pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp );
	pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity );
	pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin );
	pEffect->pParticleEffect->SetSortOrigin( vecOrigin );
}