//-----------------------------------------------------------------------------
// Purpose: Draw function for the element
//-----------------------------------------------------------------------------
void CTargetID::Paint()
{
	// No id if still choosing class
	if ( C_BaseTFPlayer::GetLocalPlayer()->GetClass() == TFCLASS_UNDECIDED )
		return;

	// Get our target's ent index
	int iEntIndex = C_BaseTFPlayer::GetLocalPlayer()->GetIDTarget();
	// Didn't find one?
	if ( !iEntIndex )
	{
		// Check to see if we should clear our ID
		if ( m_flLastChangeTime && (gpGlobals->curtime > (m_flLastChangeTime + 0.5)) )
		{
			m_flLastChangeTime = 0;
			m_sIDString[0] = 0;
			m_iLastEntIndex = 0;
		}
		else
		{
			// Keep re-using the old one
			iEntIndex = m_iLastEntIndex;
		}
	}
	else
	{
		m_flLastChangeTime = gpGlobals->curtime;
	}

	// Is this an entindex sent by the server?
	if ( iEntIndex )
	{
		C_BaseTFPlayer *pPlayer = static_cast<C_BaseTFPlayer*>(cl_entitylist->GetEnt( iEntIndex ));
		C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer();

		// Some entities we always want to check, cause the text may change
		// even while we're looking at it
		// Is it a player?
		if ( IsPlayerIndex( iEntIndex ) )
		{
			if ( pPlayer->InSameTeam(pLocalPlayer) )
			{
				// Check distance to other player, and if the player is on the same team
				float flDistSq = pPlayer->GetRenderOrigin().DistToSqr( pLocalPlayer->GetRenderOrigin() );
				if ( flDistSq < PLAYER_HINT_DISTANCE_SQ )
				{
					Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nHealth: %.0f percent\nUse to donate resources",
						pPlayer->GetPlayerName(), ((float)pPlayer->GetHealth() / (float)pPlayer->GetMaxHealth() ) * 100 );
				}
				else
				{
					Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nHealth: %.0f percent",
						pPlayer->GetPlayerName(), ((float)pPlayer->GetHealth() / (float)pPlayer->GetMaxHealth() ) * 100 );
				}
			}
			else if (( pPlayer->GetHealth() == 0) && (pLocalPlayer->GetClass() == TFCLASS_INFILTRATOR) )
			{
				Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nUse to disguise as this player", pPlayer->GetPlayerName() );
			}
			else
			{
				m_sIDString[0] = 0;
				m_iLastEntIndex = 0;
			}
		}
		else
		{
			// Objects
			C_BaseEntity *pEnt = cl_entitylist->GetEnt( iEntIndex );
			if ( !pEnt || !pEnt->InSameTeam(pLocalPlayer) )
			{
				// This can happen because the object was destroyed
				m_sIDString[0] = 0;
				m_iLastEntIndex = 0;
			}
			else
			{
				// Don't check validity if it's sent by the server
				Q_strncpy( m_sIDString, pEnt->GetIDString(), sizeof(m_sIDString) );
				m_iLastEntIndex = iEntIndex;
			}
		}
	}

	// Draw our ID string
	if ( m_sIDString[0] )
	{
		int width, height;
		int ypos = YRES(300);

		// Messagechars can't handle multiple line strings, so parse out the \n's and give it one line at a time
		char *ch = m_sIDString;
		while ( *ch )
		{
			// Find the next newline
			char *next_line;
			for ( next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ )
			{
			}

			// Stomp the newline
			char *top = next_line;
			if ( *top == '\n' )
			{
				*top = 0;
			}
			else
			{
				top = NULL;
			}

			// Draw the line
			messagechars->GetStringLength( m_hFont, &width, &height, ch );
			messagechars->DrawString( m_hFont, (ScreenWidth() - width) / 2, ypos, 255, 255, 245, 255, ch, IMessageChars::MESSAGESTRINGID_NONE );

			ypos += height;

			// Restore the newline
			if ( top ) 
			{
				*top = '\n';
			}

			// Move to the next line
			ch = next_line;
			if ( *ch == '\n' )
			{
				ch++;
			}
		}
	}
}
int CClientTools::GetEntIndex( EntitySearchResult entityToAttach )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach );
	return ent ? ent->entindex() : 0;
}
bool CClientTools::IsNPC( EntitySearchResult currentEnt )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
	return ent ? ent->IsNPC() : false;
}
//-----------------------------------------------------------------------------
// Procedurally generates the camo texture...
//-----------------------------------------------------------------------------
void CCamoMaterialProxy::GenerateCamoTexture( ITexture* pTexture, IVTFTexture *pVTFTexture )
{
	if (!m_pEnt)
		return;

#if 0
	CamoInstanceData_t *pInstanceData;
	pInstanceData = ( CamoInstanceData_t * )FindInstanceData( pEnt );
	if( !pInstanceData )
	{
		pInstanceData = ( CamoInstanceData_t * )AllocateInstanceData( pEnt );
		if( !pInstanceData )
		{
			return;
		}
		// init the instance data
	}
#endif

	Vector entityPosition;
	entityPosition = m_pEnt->GetAbsOrigin();

	QAngle entityAngles;
	entityAngles = m_pEnt->GetAbsAngles();

	// Get the bounding box for the entity
	Vector mins, maxs;
	mins = m_pEnt->WorldAlignMins();
	maxs = m_pEnt->WorldAlignMaxs();
	
	Vector traceDirection;
	Vector traceEnd;
	trace_t	traceResult;
	
	Vector forward, right, up;
	AngleVectors( entityAngles, &forward, &right, &up );
	
	Vector position, transformedPosition;
	Vector maxsMinusMins = maxs - mins;

	Vector diffuseColor[256];
	Vector baseColor;

	unsigned char camoPalette[256][3];
	// Calculate the camo palette
	//Msg( "start of loop\n" );
	int i;
	for( i = 0; i < m_CamoPatternNumColors; i++ )
	{
		GetColors( diffuseColor[i], baseColor, i,
			mins, maxsMinusMins, forward, right, up, entityPosition );
#if 1
		camoPalette[i][0] = diffuseColor[i][0] * baseColor[0] * 255.0f;
		camoPalette[i][1] = diffuseColor[i][1] * baseColor[1] * 255.0f;
		camoPalette[i][2] = diffuseColor[i][2] * baseColor[2] * 255.0f;
#endif
#if 0
		camoPalette[i][0] = baseColor[0] * 255.0f;
		camoPalette[i][1] = baseColor[1] * 255.0f;
		camoPalette[i][2] = baseColor[2] * 255.0f;
#endif
#if 0
		camoPalette[i][0] = diffuseColor[i][0] * 255.0f;
		camoPalette[i][1] = diffuseColor[i][1] * 255.0f;
		camoPalette[i][2] = diffuseColor[i][2] * 255.0f;
#endif
	}
	
	int width = pVTFTexture->Width();
	int height = pVTFTexture->Height();
	if( width != m_CamoPatternWidth || height != m_CamoPatternHeight )
	{
		return;
	}
	
	unsigned char *imageData = pVTFTexture->ImageData( 0, 0, 0 );
	enum ImageFormat imageFormat = pVTFTexture->Format();
	if( imageFormat != IMAGE_FORMAT_RGB888 )
	{
		return;
	}
	// optimize
#if 1
	int x, y;
	for( y = 0; y < height; y++ )
	{
		for( x = 0; x < width; x++ )
		{
			int offset = 3 * ( x + y * width );
			assert( offset < width * height * 3 );
			int paletteID = m_pCamoPatternImage[x + y * width];
			assert( paletteID < 256 );
#if 1
			imageData[offset + 0] = camoPalette[paletteID][0];
			imageData[offset + 1] = camoPalette[paletteID][1];
			imageData[offset + 2] = camoPalette[paletteID][2];
#else
			imageData[offset] = 255;
			imageData[offset + 1] = 0;
			imageData[offset + 2] = 0;
#endif
		}
	}
#endif
}
Example #5
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2MP_Player::CalculateIKLocks( float currentTime )
{
	if (!m_pIk) 
		return;

	int targetCount = m_pIk->m_target.Count();
	if ( targetCount == 0 )
		return;

	// In TF, we might be attaching a player's view to a walking model that's using IK. If we are, it can
	// get in here during the view setup code, and it's not normally supposed to be able to access the spatial
	// partition that early in the rendering loop. So we allow access right here for that special case.
	SpatialPartitionListMask_t curSuppressed = partition->GetSuppressedLists();
	partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
	CBaseEntity::PushEnableAbsRecomputations( false );

	for (int i = 0; i < targetCount; i++)
	{
		trace_t trace;
		CIKTarget *pTarget = &m_pIk->m_target[i];

		if (!pTarget->IsActive())
			continue;

		switch( pTarget->type)
		{
		case IK_GROUND:
			{
				pTarget->SetPos( Vector( pTarget->est.pos.x, pTarget->est.pos.y, GetRenderOrigin().z ));
				pTarget->SetAngles( GetRenderAngles() );
			}
			break;

		case IK_ATTACHMENT:
			{
				C_BaseEntity *pEntity = NULL;
				float flDist = pTarget->est.radius;

				// FIXME: make entity finding sticky!
				// FIXME: what should the radius check be?
				for ( CEntitySphereQuery sphere( pTarget->est.pos, 64 ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
				{
					C_BaseAnimating *pAnim = pEntity->GetBaseAnimating( );
					if (!pAnim)
						continue;

					int iAttachment = pAnim->LookupAttachment( pTarget->offset.pAttachmentName );
					if (iAttachment <= 0)
						continue;

					Vector origin;
					QAngle angles;
					pAnim->GetAttachment( iAttachment, origin, angles );

					// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );

					float d = (pTarget->est.pos - origin).Length();

					if ( d >= flDist)
						continue;

					flDist = d;
					pTarget->SetPos( origin );
					pTarget->SetAngles( angles );
					// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
				}

				if (flDist >= pTarget->est.radius)
				{
					// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 0, 255, 0, 0 );
					// no solution, disable ik rule
					pTarget->IKFailed( );
				}
			}
			break;
		}
	}

	CBaseEntity::PopEnableAbsRecomputations();
	partition->SuppressLists( curSuppressed, true );
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::OnBind( void *pEntity )
{
	assert ( m_AnimatedTextureVar );
	if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
		return;

	ITexture *pTexture;
	pTexture = m_AnimatedTextureVar->GetTextureValue();

	// Get the modified material vars from the entity input
	IClientRenderable *pRend = (IClientRenderable *)pEntity;
	if ( pRend )
	{
		C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
		if ( pBaseEntity )
		{
			for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
			{
				C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
				if ( !pControl )
					continue;

				if ( !pControl->HasNewAnimationCommands() )
					continue;

				// Read the data from the modify entity
				materialanimcommands_t sCommands;
				pControl->GetAnimationCommands( &sCommands );

				m_iFrameStart = sCommands.iFrameStart;
				m_iFrameEnd = sCommands.iFrameEnd;
				m_bCustomWrap = sCommands.bWrap;
				m_flCustomFramerate = sCommands.flFrameRate;
				m_bReachedEnd = false;

				m_flStartTime = gpGlobals->curtime;

				pControl->ClearAnimationCommands();
			}
		}
	}

	// Init all the vars based on whether we're using the base material settings, 
	// or the custom ones from the entity input.
	int numFrames;
	bool bWrapAnimation;
	float flFrameRate;
	int iLastFrame;

	// Do we have a custom frame section from the server?
	if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
	{
		if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
		{
			m_iFrameEnd = pTexture->GetNumAnimationFrames();
		}

		numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
		bWrapAnimation = m_bCustomWrap;
		flFrameRate = m_flCustomFramerate;
		iLastFrame = (m_iFrameEnd - 1);
	}
	else
	{
		numFrames = pTexture->GetNumAnimationFrames();
		bWrapAnimation = m_WrapAnimation;
		flFrameRate = m_FrameRate;
		iLastFrame = (numFrames - 1);
	}

	// Have we already reached the end? If so, stay there.
	if ( m_bReachedEnd && !bWrapAnimation )
	{
		m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
		return;
	}

	// NOTE: Must not use relative time based methods here
	// because the bind proxy can be called many times per frame.
	// Prevent multiple Wrap callbacks to be sent for no wrap mode
	float startTime;
	if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
	{
		startTime = m_flStartTime;
	}
	else
	{
		startTime = GetAnimationStartTime(pEntity);
	}
	float deltaTime = gpGlobals->curtime - startTime;
	float prevTime = deltaTime - gpGlobals->frametime;

	// Clamp..
	if (deltaTime < 0.0f)
		deltaTime = 0.0f;
	if (prevTime < 0.0f)
		prevTime = 0.0f;

	float frame = flFrameRate * deltaTime;	
	float prevFrame = flFrameRate * prevTime;

	int intFrame = ((int)frame) % numFrames; 
	int intPrevFrame = ((int)prevFrame) % numFrames;

	if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
	{
		intFrame += m_iFrameStart;
		intPrevFrame += m_iFrameStart;
	}

	// Report wrap situation...
	if (intPrevFrame > intFrame)
	{
		m_bReachedEnd = true;

		if (bWrapAnimation)
		{
			AnimationWrapped( pEntity );
		}
		else
		{
			// Only sent the wrapped message once.
			// when we're in non-wrapping mode
			if (prevFrame < numFrames)
				AnimationWrapped( pEntity );
			intFrame = numFrames - 1;
		}
	}

	m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );

	if ( ToolsEnabled() )
	{
		ToolFramework_RecordMaterialParams( GetMaterial() );
	}
}
Example #7
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : scale - 
//			attachmentIndex - 
//			bOneFrame - 
//-----------------------------------------------------------------------------
void FX_MuzzleEffectAttached( 
	float scale, 
	ClientEntityHandle_t hEntity, 
	int attachmentIndex, 
	unsigned char *pFlashColor,
	bool bOneFrame )
{
	VPROF_BUDGET( "FX_MuzzleEffect", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	// If the material isn't available, let's not do anything.
	if ( g_Mat_SMG_Muzzleflash[0] == NULL )
	{
		return;
	}
	
	CSmartPtr<CLocalSpaceEmitter> pSimple = CLocalSpaceEmitter::Create( "MuzzleFlash", hEntity, attachmentIndex );
	Assert( pSimple );
	if ( pSimple == NULL )
		return;
	
	// Lock our bounding box
	pSimple->GetBinding().SetBBox( -( Vector( 16, 16, 16 ) * scale ), ( Vector( 16, 16, 16 ) * scale ) );
	
	SimpleParticle *pParticle;
	Vector			forward(1,0,0), offset;

	float flScale = random->RandomFloat( scale-0.25f, scale+0.25f );

	if ( flScale < 0.5f )
	{
		flScale = 0.5f;
	}
	else if ( flScale > 8.0f )
	{
		flScale = 8.0f;
	}

	//
	// Flash
	//

	int i;
	for ( i = 1; i < 9; i++ )
	{
		offset = (forward * (i*2.0f*scale));

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_SMG_Muzzleflash[random->RandomInt(0,3)], offset );
			
		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime		= 0.0f;
		pParticle->m_flDieTime		= bOneFrame ? 0.0001f : 0.1f;

		pParticle->m_vecVelocity.Init();

		if ( !pFlashColor )
		{
			pParticle->m_uchColor[0]	= 255;
			pParticle->m_uchColor[1]	= 255;
			pParticle->m_uchColor[2]	= 255;
		}
		else
		{
			pParticle->m_uchColor[0]	= pFlashColor[0];
			pParticle->m_uchColor[1]	= pFlashColor[1];
			pParticle->m_uchColor[2]	= pFlashColor[2];
		}

		pParticle->m_uchStartAlpha	= 255;
		pParticle->m_uchEndAlpha	= 128;

		pParticle->m_uchStartSize	= (random->RandomFloat( 6.0f, 9.0f ) * (12-(i))/9) * flScale;
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize;
		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= 0.0f;
	}


	if ( !ToolsEnabled() )
		return;

	if ( !clienttools->IsInRecordingMode() )
		return;

	C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( hEntity );
	if ( pEnt )
	{
		pEnt->RecordToolMessage();
	}

	// NOTE: Particle system destruction message will be sent by the particle effect itself.
	int nId = pSimple->AllocateToolParticleEffectId();

	KeyValues *msg = new KeyValues( "OldParticleSystem_Create" );
	msg->SetString( "name", "FX_MuzzleEffectAttached" );
	msg->SetInt( "id", nId );
	msg->SetFloat( "time", gpGlobals->curtime );

	KeyValues *pEmitter = msg->FindKey( "DmeSpriteEmitter", true );
	pEmitter->SetInt( "count", 9 );
	pEmitter->SetFloat( "duration", 0 );
	pEmitter->SetString( "material", "effects/muzzleflash2" ); // FIXME - create DmeMultiMaterialSpriteEmitter to support the 4 materials of muzzleflash
	pEmitter->SetInt( "active", true );

	KeyValues *pInitializers = pEmitter->FindKey( "initializers", true );

	KeyValues *pPosition = pInitializers->FindKey( "DmeLinearAttachedPositionInitializer", true );
	pPosition->SetPtr( "entindex", (void*)pEnt->entindex() );
	pPosition->SetInt( "attachmentIndex", attachmentIndex );
	pPosition->SetFloat( "linearOffsetX", 2.0f * scale );

	// TODO - create a DmeConstantLifetimeInitializer
	KeyValues *pLifetime = pInitializers->FindKey( "DmeRandomLifetimeInitializer", true );
	pLifetime->SetFloat( "minLifetime", bOneFrame ? 1.0f / 24.0f : 0.1f );
	pLifetime->SetFloat( "maxLifetime", bOneFrame ? 1.0f / 24.0f : 0.1f );

	KeyValues *pVelocity = pInitializers->FindKey( "DmeConstantVelocityInitializer", true );
	pVelocity->SetFloat( "velocityX", 0.0f );
	pVelocity->SetFloat( "velocityY", 0.0f );
	pVelocity->SetFloat( "velocityZ", 0.0f );

	KeyValues *pRoll = pInitializers->FindKey( "DmeRandomRollInitializer", true );
	pRoll->SetFloat( "minRoll", 0.0f );
	pRoll->SetFloat( "maxRoll", 360.0f );

	// TODO - create a DmeConstantRollSpeedInitializer
	KeyValues *pRollSpeed = pInitializers->FindKey( "DmeRandomRollSpeedInitializer", true );
	pRollSpeed->SetFloat( "minRollSpeed", 0.0f );
	pRollSpeed->SetFloat( "maxRollSpeed", 0.0f );

	// TODO - create a DmeConstantColorInitializer
	KeyValues *pColor = pInitializers->FindKey( "DmeRandomInterpolatedColorInitializer", true );
	Color color( pFlashColor ? pFlashColor[ 0 ] : 255, pFlashColor ? pFlashColor[ 1 ] : 255, pFlashColor ? pFlashColor[ 2 ] : 255, 255 );
	pColor->SetColor( "color1", color );
	pColor->SetColor( "color2", color );

	// TODO - create a DmeConstantAlphaInitializer
	KeyValues *pAlpha = pInitializers->FindKey( "DmeRandomAlphaInitializer", true );
	pAlpha->SetInt( "minStartAlpha", 255 );
	pAlpha->SetInt( "maxStartAlpha", 255 );
	pAlpha->SetInt( "minEndAlpha", 128 );
	pAlpha->SetInt( "maxEndAlpha", 128 );

	// size = rand(6..9) * indexed(12/9..4/9) * flScale = rand(6..9) * ( 4f + f * i )
	KeyValues *pSize = pInitializers->FindKey( "DmeMuzzleFlashSizeInitializer", true );
	float f = flScale / 9.0f;
	pSize->SetFloat( "indexedBase", 4.0f * f );
	pSize->SetFloat( "indexedDelta", f );
	pSize->SetFloat( "minRandomFactor", 6.0f );
	pSize->SetFloat( "maxRandomFactor", 9.0f );

/*
	KeyValues *pUpdaters = pEmitter->FindKey( "updaters", true );

	pUpdaters->FindKey( "DmePositionVelocityUpdater", true );
	pUpdaters->FindKey( "DmeRollUpdater", true );
	pUpdaters->FindKey( "DmeAlphaLinearUpdater", true );
	pUpdaters->FindKey( "DmeSizeUpdater", true );
*/
	ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
	msg->deleteThis();
}
bool CClientTools::IsCombatCharacter( EntitySearchResult currentEnt )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
	return ent ? ent->IsBaseCombatCharacter() : false;
}
bool CClientTools::IsRagdoll( EntitySearchResult currentEnt )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
	C_BaseAnimating *pBaseAnimating = ent ? ent->GetBaseAnimating() : NULL;
	return pBaseAnimating ? pBaseAnimating->IsClientRagdoll() : false;
}
Example #10
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponMedigun::UpdateEffects( void )
{
	CTFPlayer *pFiringPlayer = ToTFPlayer( GetOwnerEntity() );
	if ( !pFiringPlayer )
		return;

	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	C_BaseEntity *pEffectOwner = this;
	if ( pLocalPlayer == pFiringPlayer )
	{
		pEffectOwner = pLocalPlayer->GetViewModel();
		if ( !pEffectOwner )
			return;
	}

	// Remove all the effects
	if ( pEffectOwner )
	{
		pEffectOwner->ParticleProp()->StopEmission( m_hHealingTargetEffect.pEffect );
	}
	else
	{
		m_hHealingTargetEffect.pEffect->StopEmission();
	}
	m_hHealingTargetEffect.pTarget = NULL;
	m_hHealingTargetEffect.pEffect = NULL;

	// Don't add targets if the medic is dead
	if ( !pEffectOwner || pFiringPlayer->IsPlayerDead() || !pFiringPlayer->IsPlayerClass( TF_CLASS_MEDIC ) )
		return;

	// Add our targets
	// Loops through the healing targets, and make sure we have an effect for each of them
	if ( m_hHealingTarget )
	{
		if ( m_hHealingTargetEffect.pTarget == m_hHealingTarget )
			return;

		const char *pszEffectName;
		if (m_bChargeRelease)
		{
			switch (GetTeamNumber())
			{
			case TF_TEAM_BLUE:
				pszEffectName = "medicgun_beam_blue_invun";
				break;
			case TF_TEAM_RED:
				pszEffectName = "medicgun_beam_red_invun";
				break;
			case TF_TEAM_GREEN:
				pszEffectName = "medicgun_beam_green_invun";
				break;
			case TF_TEAM_YELLOW:
				pszEffectName = "medicgun_beam_yellow_invun";
				break;
			default:
				pszEffectName = "medicgun_beam_blue";
				break;
			}
		}
		else
		{
			switch (GetTeamNumber())
			{
			case TF_TEAM_BLUE:
				pszEffectName = "medicgun_beam_blue";
				break;
			case TF_TEAM_RED:
				pszEffectName = "medicgun_beam_red";
				break;
			case TF_TEAM_GREEN:
				pszEffectName = "medicgun_beam_green";
				break;
			case TF_TEAM_YELLOW:
				pszEffectName = "medicgun_beam_yellow";
				break;
			default:
				pszEffectName = "medicgun_beam_blue";
				break;
			}
		}


		CNewParticleEffect *pEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" );
		pEffectOwner->ParticleProp()->AddControlPoint( pEffect, 1, m_hHealingTarget, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector(0,0,50) );

		m_hHealingTargetEffect.pTarget = m_hHealingTarget;
		m_hHealingTargetEffect.pEffect = pEffect;
	}
}
Example #11
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponMedigun::ManageChargeEffect( void )
{
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	C_BaseEntity *pEffectOwner = this;

	if ( pLocalPlayer == NULL )
		return;

	if ( pLocalPlayer == GetTFPlayerOwner() )
	{
		pEffectOwner = pLocalPlayer->GetViewModel();
		if ( !pEffectOwner )
			return;
	}

	bool bOwnerTaunting = false;

	if ( GetTFPlayerOwner() && GetTFPlayerOwner()->m_Shared.InCond( TF_COND_TAUNTING ) == true )
	{
		bOwnerTaunting = true;
	}

	if ( GetTFPlayerOwner() && bOwnerTaunting == false && m_bHolstered == false && ( m_flChargeLevel >= 1.0f || m_bChargeRelease == true ) )
	{
		if ( m_pChargeEffect == NULL )
		{
			char *pszEffectName = NULL;

			switch( GetTFPlayerOwner()->GetTeamNumber() )
			{
			case TF_TEAM_BLUE:
				pszEffectName = "medicgun_invulnstatus_fullcharge_blue";
				break;
			case TF_TEAM_RED:
				pszEffectName = "medicgun_invulnstatus_fullcharge_red";
				break;
			case TF_TEAM_GREEN:
				pszEffectName = "medicgun_invulnstatus_fullcharge_green";
				break;
			case TF_TEAM_YELLOW:
				pszEffectName = "medicgun_invulnstatus_fullcharge_yellow";
				break;
			default:
				pszEffectName = "";
				break;
			}

			m_pChargeEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" );
		}

		if ( m_pChargedSound == NULL )
		{
			CLocalPlayerFilter filter;

			CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();

			m_pChargedSound = controller.SoundCreate( filter, entindex(), "WeaponMedigun.Charged" );
			controller.Play( m_pChargedSound, 1.0, 100 );
		}
	}
	else
	{
		if ( m_pChargeEffect != NULL )
		{
			pEffectOwner->ParticleProp()->StopEmission( m_pChargeEffect );
			m_pChargeEffect = NULL;
		}

		if ( m_pChargedSound != NULL )
		{
			CSoundEnvelopeController::GetController().SoundDestroy( m_pChargedSound );
			m_pChargedSound = NULL;
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : int - 
//-----------------------------------------------------------------------------
int	C_GunshipFX::DrawModel( int )
{
	static color32 white = {255,255,255,255};
	Vector params[GUNSHIPFX_PARAMETERS];
	bool hasParam[GUNSHIPFX_PARAMETERS];

	if ( !m_active )
		return 1;

	C_BaseEntity *ent = cl_entitylist->GetEnt( m_entityIndex );
	if ( ent )
	{
		QAngle angles;
		ent->GetAttachment( m_attachment, m_worldPosition, angles );
	}

	Vector test;
	m_t += gpGlobals->frametime;
	if ( m_tMax > 0 )
	{
		m_t = clamp( m_t, 0, m_tMax );
		m_beamEndPosition = m_worldPosition;
	}
	float t = m_t;

	bool hasAny = false;
	memset( hasParam, 0, sizeof(hasParam) );
	for ( int i = 0; i < GUNSHIPFX_PARAMETERS; i++ )
	{
		hasParam[i] = g_GunshipCannonEnvelope.m_parameters[i].Interp( params[i], t );
		hasAny = hasAny || hasParam[i];
	}

	// draw the narrow beam
	if ( hasParam[GUNSHIPFX_NARROW_BEAM_COLOR] && hasParam[GUNSHIPFX_NARROW_BEAM_SIZE] )
	{
		IMaterial *pMat = materials->FindMaterial( "sprites/bluelaser1", TEXTURE_GROUP_CLIENT_EFFECTS );
		float width = NARROW_BEAM_WIDTH * params[GUNSHIPFX_NARROW_BEAM_SIZE].x;
		color32 color;
		float bright = params[GUNSHIPFX_NARROW_BEAM_COLOR].x;
		ScaleColor( color, white, bright );

		//Gunship_DrawLine( m_beamEndPosition, m_targetPosition, width, pMat, color );
		FX_DrawLine( m_beamEndPosition, m_targetPosition, width, pMat, color );
	}

	// glowy blue flare sprite
	if ( hasParam[GUNSHIPFX_FLARE_COLOR] && hasParam[GUNSHIPFX_FLARE_SIZE] )
	{
		IMaterial *pMat = materials->FindMaterial( "effects/blueblackflash", TEXTURE_GROUP_CLIENT_EFFECTS );
		float size = FLARE_SIZE * params[GUNSHIPFX_FLARE_SIZE].x;
		color32 color;
		float bright = params[GUNSHIPFX_FLARE_COLOR].x;
		ScaleColor( color, white, bright );
		color.a = (int)(255 * params[GUNSHIPFX_DARKNESS].x);
		materials->Bind( pMat, (IClientRenderable*)this );
		Gunship_DrawSprite( m_worldPosition, size, color, true );
	}

	if ( hasParam[GUNSHIPFX_AFTERGLOW_COLOR] )
	{
		// Muzzle effect
		dlight_t *dl = effects->CL_AllocDlight( m_entityIndex );
		dl->origin = m_worldPosition;
		dl->color.r = 40*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
		dl->color.g = 60*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
		dl->color.b = 255*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
		dl->color.exponent = 5;
		dl->radius = 128.0f;
		dl->die = gpGlobals->curtime + 0.001;
	}

	if ( m_t >= 4.0 && !hasAny )
	{
		EffectShutdown();
	}

	return 1;
}
//-----------------------------------------------------------------------------
// Purpose: First-person function call after viewmodel has been drawn
//-----------------------------------------------------------------------------
void CWeaponGravityGun::ViewModelDrawn( C_BaseViewModel *pBaseViewModel )
{
	if ( !m_active )
		return;

	// Render our effects
	C_BasePlayer *pOwner = ToBasePlayer( GetOwner() );

	if ( !pOwner )
		return;

	Vector points[3];
	QAngle tmpAngle;

	C_BaseEntity *pObject = m_hObject;
	//if ( pObject == NULL )
	//	return;

	pBaseViewModel->GetAttachment( 1, points[0], tmpAngle );

	// a little noise 11t & 13t should be somewhat non-periodic looking
	//points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 );
	if ( pObject == NULL )
	{
		//points[2] = m_targetPosition;
		trace_t tr;
		TraceLine( &tr );
		points[2] = tr.endpos;
	}
	else
	{
		pObject->EntityToWorldSpace(m_worldPosition, &points[2]);
	}

	Vector forward, right, up;
	QAngle playerAngles = pOwner->EyeAngles();
	AngleVectors( playerAngles, &forward, &right, &up );
	Vector vecSrc = pOwner->Weapon_ShootPosition( );
	points[1] = vecSrc + 0.5f * (forward * points[2].DistTo(points[0]));
	
	IMaterial *pMat = materials->FindMaterial( "sprites/physbeam1", TEXTURE_GROUP_CLIENT_EFFECTS );
	if ( pObject )
		pMat = materials->FindMaterial( "sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS );
	Vector color;
	color.Init(1,1,1);

	// Now draw it.
	CViewSetup beamView = *view->GetPlayerViewSetup();

	Frustum dummyFrustum;
	render->Push3DView( beamView, 0, NULL, dummyFrustum );

	float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime;
	CMatRenderContextPtr pRenderContext( materials );
	pRenderContext->Bind( pMat );
#if 1
	// HACK HACK:  Munge the depth range to prevent view model from poking into walls, etc.
	// Force clipped down range
	pRenderContext->DepthRange( 0.1f, 0.2f );
#endif
	DrawBeamQuadratic( points[0], points[1], points[2], pObject ? 13/3.0f : 13/5.0f, color, scrollOffset );
	DrawBeamQuadratic( points[0], points[1], points[2], pObject ? 13/3.0f : 13/5.0f, color, -scrollOffset );

	IMaterial *pMaterial = materials->FindMaterial( "sprites/physglow", TEXTURE_GROUP_CLIENT_EFFECTS );

	color32 clr={0,64,255,255};
	if ( pObject )
	{
		clr.r = 186;
		clr.g = 253;
		clr.b = 247;
		clr.a = 255;
	}

	float scale = random->RandomFloat( 3, 5 ) * ( pObject ? 3 : 2 );

	// Draw the sprite
	pRenderContext->Bind( pMaterial );
	for ( int i = 0; i < 3; i++ )
	{
		DrawSprite( points[2], scale, scale, clr );
	}
#if 1
	pRenderContext->DepthRange( 0.0f, 1.0f );
#endif

	render->PopView( dummyFrustum );

	// Pass this back up
	BaseClass::ViewModelDrawn( pBaseViewModel );
}
//-----------------------------------------------------------------------------
// Purpose: Third-person function call to render world model
//-----------------------------------------------------------------------------
int CWeaponGravityGun::DrawModel( int flags )
{
	// Only render these on the transparent pass
	if ( flags & STUDIO_TRANSPARENCY )
	{
		if ( !m_active )
			return 0;

		C_BasePlayer *pOwner = ToBasePlayer( GetOwner() );

		if ( !pOwner )
			return 0;

		Vector points[3];
		QAngle tmpAngle;

		C_BaseEntity *pObject = m_hObject;
		//if ( pObject == NULL )
		//	return 0;

		GetAttachment( 1, points[0], tmpAngle );

		// a little noise 11t & 13t should be somewhat non-periodic looking
		//points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 );
		if ( pObject == NULL )
		{
			//points[2] = m_targetPosition;
			trace_t tr;
			TraceLine( &tr );
			points[2] = tr.endpos;
		}
		else
		{
			pObject->EntityToWorldSpace( m_worldPosition, &points[2] );
		}

		Vector forward, right, up;
		QAngle playerAngles = pOwner->EyeAngles();
		AngleVectors( playerAngles, &forward, &right, &up );
		if ( pObject == NULL )
		{
			Vector vecDir = points[2] - points[0];
			VectorNormalize( vecDir );
			points[1] = points[0] + 0.5f * (vecDir * points[2].DistTo(points[0]));
		}
		else
		{
			Vector vecSrc = pOwner->Weapon_ShootPosition( );
			points[1] = vecSrc + 0.5f * (forward * points[2].DistTo(points[0]));
		}
		
		IMaterial *pMat = materials->FindMaterial( "sprites/physbeam1", TEXTURE_GROUP_CLIENT_EFFECTS );
		if ( pObject )
			pMat = materials->FindMaterial( "sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS );
		Vector color;
		color.Init(1,1,1);

		float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime;
		CMatRenderContextPtr pRenderContext( materials );
		pRenderContext->Bind( pMat );
		DrawBeamQuadratic( points[0], points[1], points[2], pObject ? 13/3.0f : 13/5.0f, color, scrollOffset );
		DrawBeamQuadratic( points[0], points[1], points[2], pObject ? 13/3.0f : 13/5.0f, color, -scrollOffset );

		IMaterial *pMaterial = materials->FindMaterial( "sprites/physglow", TEXTURE_GROUP_CLIENT_EFFECTS );

		color32 clr={0,64,255,255};
		if ( pObject )
		{
			clr.r = 186;
			clr.g = 253;
			clr.b = 247;
			clr.a = 255;
		}

		float scale = random->RandomFloat( 3, 5 ) * ( pObject ? 3 : 2 );

		// Draw the sprite
		pRenderContext->Bind( pMaterial );
		for ( int i = 0; i < 3; i++ )
		{
			DrawSprite( points[2], scale, scale, clr );
		}
		return 1;
	}

	// Only do this on the opaque pass
	return BaseClass::DrawModel( flags );
}
Example #15
0
void FX_ThumperDust( const CEffectData &data )
{
	Vector vecDustColor;
	vecDustColor.x = 0.85f;
	vecDustColor.y = 0.75f;
	vecDustColor.z = 0.52f;

	CSmartPtr<ThumperDustEmitter> pSimple = ThumperDustEmitter::Create( "thumperdust" );

	C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
	if ( pEnt )
	{
		Vector vWorldMins, vWorldMaxs;
		float scale = pEnt->CollisionProp()->BoundingRadius();
		vWorldMins[0] = data.m_vOrigin[0] - scale;
		vWorldMins[1] = data.m_vOrigin[1] - scale;
		vWorldMins[2] = data.m_vOrigin[2] - scale;
		vWorldMaxs[0] = data.m_vOrigin[0] + scale;
		vWorldMaxs[1] = data.m_vOrigin[1] + scale;
		vWorldMaxs[2] = data.m_vOrigin[2] + scale;
		pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
	}

	pSimple->SetSortOrigin( data.m_vOrigin );
	pSimple->SetNearClip( 32, 64 );

	SimpleParticle	*pParticle = NULL;

	Vector	offset;

	//int	numPuffs = IsXbox() ? THUMPER_MAX_PARTICLES/2 : THUMPER_MAX_PARTICLES;
	int	numPuffs = THUMPER_MAX_PARTICLES;

	float flYaw = 0;
	float flIncr = (2*M_PI) / (float) numPuffs; // Radians
	Vector forward;
	Vector vecColor;
	int i = 0;

	float flScale = min( data.m_flScale, 255 );

	// Setup the color for these particles
	engine->ComputeLighting( data.m_vOrigin, NULL, true, vecColor );
	VectorLerp( vecColor, vecDustColor, 0.5, vecColor );
	vecColor *= 255;

	for ( i = 0; i < numPuffs; i++ )
	{
		flYaw += flIncr;
		SinCos( flYaw, &forward.y, &forward.x );	
		forward.z = 0.0f;

		offset = ( RandomVector( -4.0f, 4.0f ) + data.m_vOrigin ) + ( forward * 128.0f );

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset );
		if ( pParticle != NULL )
		{	
			pParticle->m_flLifetime		= 0.0f;
			pParticle->m_flDieTime		= 1.5f;
	
			Vector dir = (offset - data.m_vOrigin);
			float length = dir.Length();
			VectorNormalize( dir );

			pParticle->m_vecVelocity	= dir * ( length * 2.0f );
			pParticle->m_vecVelocity[2]	= data.m_flScale / 3;

			pParticle->m_uchColor[0]	= vecColor[0];
			pParticle->m_uchColor[1]	= vecColor[1];
			pParticle->m_uchColor[2]	= vecColor[2];

			pParticle->m_uchStartAlpha	= random->RandomInt( 64, 96 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_uchStartSize	= flScale * 0.25f;
			pParticle->m_uchEndSize		= flScale * 0.5f;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -6.0f, 6.0f );
		}
	}
}
bool CClientTools::IsViewModelOrAttachment( EntitySearchResult currentEnt )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
	C_BaseAnimating *pBaseAnimating = ent ? ent->GetBaseAnimating() : NULL;
	return pBaseAnimating ? pBaseAnimating->IsViewModelOrAttachment() : false;
}
Example #17
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void TFExplosionCallback( const Vector &vecOrigin, const Vector &vecNormal, int iWeaponID, ClientEntityHandle_t hEntity, C_TFPlayer *pPlayer, int iTeam, bool bCrit, int iItemID )
{
	// Get the weapon information.
	CTFWeaponInfo *pWeaponInfo = NULL;
	switch ( iWeaponID )
	{
	case TF_WEAPON_GRENADE_PIPEBOMB:
	case TF_WEAPON_GRENADE_DEMOMAN:
		pWeaponInfo = GetTFWeaponInfo( TF_WEAPON_PIPEBOMBLAUNCHER );
		break;
	default:
		pWeaponInfo = GetTFWeaponInfo( iWeaponID );
		break;
	}

	bool bIsPlayer = false;
	if ( hEntity.Get() )
	{
		C_BaseEntity *pEntity = C_BaseEntity::Instance( hEntity );
		if ( pEntity && pEntity->IsPlayer() )
		{
			bIsPlayer = true;
		}
	}

	// Calculate the angles, given the normal.
	bool bIsWater = ( UTIL_PointContents( vecOrigin ) & CONTENTS_WATER );
	bool bInAir = false;
	QAngle angExplosion( 0.0f, 0.0f, 0.0f );

	// Cannot use zeros here because we are sending the normal at a smaller bit size.
	if ( fabs( vecNormal.x ) < 0.05f && fabs( vecNormal.y ) < 0.05f && fabs( vecNormal.z ) < 0.05f )
	{
		bInAir = true;
		angExplosion.Init();
	}
	else
	{
		VectorAngles( vecNormal, angExplosion );
		bInAir = false;
	}

	bool bDeathmatchOverride = ( pPlayer && TFGameRules()->IsDeathmatch() );

	// Base explosion effect and sound.
	const char *pszEffect = "explosion";
	const char *pszSound = "BaseExplosionEffect.Sound";

	if ( pWeaponInfo )
	{
		// Explosions.
		if ( bIsWater )
		{
			if ( bCrit && pWeaponInfo->m_szExplosionWaterEffect_Crit[0] )
			{
				pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionWaterEffect_Crit, iTeam, bDeathmatchOverride );
			}
			else if ( pWeaponInfo->m_szExplosionWaterEffect[0] )
			{
				pszEffect = pWeaponInfo->m_szExplosionWaterEffect;
			}
		}
		else
		{
			if ( bIsPlayer || bInAir )
			{
				if ( bCrit && pWeaponInfo->m_szExplosionPlayerEffect_Crit[0] )
				{
					pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionPlayerEffect_Crit, iTeam, bDeathmatchOverride );
				}
				else if ( pWeaponInfo->m_szExplosionPlayerEffect[0] )
				{
					pszEffect = pWeaponInfo->m_szExplosionPlayerEffect;
				}
			}
			else
			{
				if ( bCrit && pWeaponInfo->m_szExplosionEffect_Crit[0] )
				{
					pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionEffect_Crit, iTeam, bDeathmatchOverride );
				}
				else if ( pWeaponInfo->m_szExplosionEffect[0] )
				{
					pszEffect = pWeaponInfo->m_szExplosionEffect;
				}
			}
		}

		// Sound.
		if ( pWeaponInfo->m_szExplosionSound[0] != '\0' )
		{
			pszSound = pWeaponInfo->m_szExplosionSound;
		}
	}

	// Allow schema to override explosion sound.
	if ( iItemID >= 0 )
	{
		CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinition( iItemID );
		if ( pItemDef && pItemDef->GetVisuals()->aWeaponSounds[SPECIAL1][0] != '\0' )
		{
			pszSound = pItemDef->GetVisuals()->aWeaponSounds[SPECIAL1];
		}
	}
	
	CLocalPlayerFilter filter;
	C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, pszSound, &vecOrigin );

	if ( bDeathmatchOverride )
	{
		DispatchParticleEffect( pszEffect, vecOrigin, angExplosion, pPlayer->m_vecPlayerColor, vec3_origin, true );
	}
	else
	{
		DispatchParticleEffect( pszEffect, vecOrigin, angExplosion );
	}
}
Example #18
0
//-----------------------------------------------------------------------------
// Purpose: 
// Output : int
//-----------------------------------------------------------------------------
int C_SpriteRenderer::DrawSprite( 
	IClientEntity *entity,
	const model_t *model, 
	const Vector& origin, 
	const QAngle& angles,
	float frame,
	IClientEntity *attachedto,
	int attachmentindex,
	int rendermode,
	int renderfx,
	int alpha,
	int r, 
	int g, 
	int b,
	float scale,
	float flHDRColorScale
	)
{
	VPROF_BUDGET( "C_SpriteRenderer::DrawSprite", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	if ( !r_drawsprites.GetBool() || !model || modelinfo->GetModelType( model ) != mod_sprite )
	{
		return 0;
	}

	// Get extra data
	CEngineSprite *psprite = (CEngineSprite *)modelinfo->GetModelExtraData( model );
	if ( !psprite )
	{
		return 0;
	}

	Vector effect_origin;
	VectorCopy( origin, effect_origin );

	// Use attachment point
	if ( attachedto )
	{
		C_BaseEntity *ent = attachedto->GetBaseEntity();
		if ( ent )
		{
			// don't draw viewmodel effects in reflections
			if ( CurrentViewID() == VIEW_REFLECTION )
			{
				if ( g_pClientLeafSystem->IsRenderingWithViewModels( ent->RenderHandle() ) )
					return 0;
			}
			QAngle temp;
			ent->GetAttachment( attachmentindex, effect_origin, temp );
		}
	}

	if ( rendermode != kRenderNormal )
	{
		float blend = render->GetBlend();

		// kRenderGlow and kRenderWorldGlow have a special blending function
		if (( rendermode == kRenderGlow ) || ( rendermode == kRenderWorldGlow ))
		{
			blend *= GlowBlend( psprite, effect_origin, rendermode, renderfx, alpha, &scale );

			// Fade out the sprite depending on distance from the view origin.
			r *= blend;
			g *= blend;
			b *= blend;
		}

		render->SetBlend( blend );
		if ( blend <= 0.0f )
		{
			return 0;
		}
	}
	
	// Get orthonormal basis
	Vector forward, right, up;
	GetSpriteAxes( (SPRITETYPE)psprite->GetOrientation(), origin, angles, forward, right, up );

	// Draw
	DrawSpriteModel( 
		entity,
		psprite, 
		effect_origin,
		scale,
		frame, 
		rendermode, 
		r, 
		g, 
		b,
		alpha, 
		forward, right, up, flHDRColorScale );

	return 1;
}
Example #19
0
//-----------------------------------------------------------------------------
// Sets up the view parameters
//-----------------------------------------------------------------------------
void CViewRender::SetUpView()
{
	ASSERT_LOCAL_PLAYER_RESOLVABLE();
	int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();

	m_bAllowViewAccess = true;
	VPROF("CViewRender::SetUpView");
	// Initialize view structure with default values
	float farZ = GetZFar();

	CViewSetup &view = GetView();

	view.zFar				= farZ;
	view.zFarViewmodel	= farZ;
	// UNDONE: Make this farther out? 
	//  closest point of approach seems to be view center to top of crouched box
	view.zNear			= GetZNear();
	view.zNearViewmodel	= 1;
	view.fov				= default_fov.GetFloat();

	view.m_bOrtho			= false;

	// Enable spatial partition access to edicts
	partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );

	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	bool bNoViewEnt = false;
	if( pPlayer == NULL )
	{
		pPlayer = GetSplitScreenViewPlayer( nSlot );
		bNoViewEnt = true;
	}

	if ( g_bEngineIsHLTV )
	{
		HLTVCamera()->CalcView( view.origin, view.angles, view.fov );
	}
#if defined( REPLAY_ENABLED )
	else if ( engine->IsReplay() )
	{
		ReplayCamera()->CalcView( view.origin, view.angles, view.fov );
	}
#endif
	else
	{
		// FIXME: Are there multiple views? If so, then what?
		// FIXME: What happens when there's no player?
		if (pPlayer)
		{
			pPlayer->CalcView( view.origin, view.angles, view.zNear, view.zFar, view.fov );

			// If we are looking through another entities eyes, then override the angles/origin for GetView()
			int viewentity = render->GetViewEntity();

			if ( !bNoViewEnt && !g_nKillCamMode && (pPlayer->entindex() != viewentity) )
			{
				C_BaseEntity *ve = cl_entitylist->GetEnt( viewentity );
				if ( ve )
				{
					VectorCopy( ve->GetAbsOrigin(), view.origin );
					VectorCopy( ve->GetAbsAngles(), view.angles );
				}
			}

			pPlayer->CalcViewModelView( view.origin, view.angles );

			// Is this the proper place for this code?
			if ( cl_camera_follow_bone_index.GetInt() >= -1 && input->CAM_IsThirdPerson() )
			{
				VectorCopy( g_cameraFollowPos, view.origin );
			}
		}

		// Even if the engine is paused need to override the view
		// for keeping the camera control during pause.
		GetClientMode()->OverrideView( &GetView() );
	}

	// give the toolsystem a chance to override the view
	ToolFramework_SetupEngineView( view.origin, view.angles, view.fov );

	if ( engine->IsPlayingDemo() )
	{
		if ( cl_demoviewoverride.GetFloat() > 0.0f )
		{
			// Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
			CalcDemoViewOverride( view.origin, view.angles );
		}
		else
		{
			s_DemoView = view.origin;
			s_DemoAngle = view.angles;
		}
	}

	// Disable spatial partition access
	partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );

	//Find the offset our current FOV is from the default value
	float flFOVOffset = default_fov.GetFloat() - view.fov;

	//Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
	view.fovViewmodel = GetClientMode()->GetViewModelFOV() - flFOVOffset;

	// Compute the world->main camera transform
	ComputeCameraVariables( view.origin, view.angles, 
		&g_vecVForward[ nSlot ], &g_vecVRight[ nSlot ], &g_vecVUp[ nSlot ], &g_matCamInverse[ nSlot ] );

	// set up the hearing origin...
	AudioState_t audioState;
	audioState.m_Origin = view.origin;
	audioState.m_Angles = view.angles;
	audioState.m_bIsUnderwater = pPlayer && pPlayer->AudioStateIsUnderwater( view.origin );

	ToolFramework_SetupAudioState( audioState );

	view.origin = audioState.m_Origin;
	view.angles = audioState.m_Angles;

	GetClientMode()->OverrideAudioState( &audioState );
	engine->SetAudioState( audioState );

	g_vecPrevRenderOrigin[ nSlot ] = g_vecRenderOrigin[ nSlot ];
	g_vecPrevRenderAngles[ nSlot ] = g_vecRenderAngles[ nSlot ];
	g_vecRenderOrigin[ nSlot ] = view.origin;
	g_vecRenderAngles[ nSlot ] = view.angles;

#ifdef DBGFLAG_ASSERT
	s_DbgSetupOrigin[ nSlot ] = view.origin;
	s_DbgSetupAngles[ nSlot ] = view.angles;
#endif

	m_bAllowViewAccess = false;
}
Example #20
0
//-----------------------------------------------------------------------------
// Purpose: Return the origin & angles for a projectile fired from the player's gun
//-----------------------------------------------------------------------------
void CTFWeaponBaseGun::GetProjectileFireSetup( CTFPlayer *pPlayer, Vector vecOffset, Vector *vecSrc, QAngle *angForward, bool bHitTeammates /* = true */ )
{
	Vector vecForward, vecRight, vecUp;
	AngleVectors( pPlayer->EyeAngles(), &vecForward, &vecRight, &vecUp );

	Vector vecShootPos = pPlayer->Weapon_ShootPosition();

	// Estimate end point
	Vector endPos = vecShootPos + vecForward * 2000;	

	// Trace forward and find what's in front of us, and aim at that
	trace_t tr;

	if ( bHitTeammates )
	{
		CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE );
		UTIL_TraceLine( vecShootPos, endPos, MASK_SOLID, &filter, &tr );
	}
	else
	{
		CTraceFilterIgnoreTeammates filter( pPlayer, COLLISION_GROUP_NONE, pPlayer->GetTeamNumber() );
		UTIL_TraceLine( vecShootPos, endPos, MASK_SOLID, &filter, &tr );
	}

#ifndef CLIENT_DLL
	// Offset actual start point
	*vecSrc = vecShootPos + (vecForward * vecOffset.x) + (vecRight * vecOffset.y) + (vecUp * vecOffset.z);
#else
	// If we're seeing another player shooting the projectile, move their start point to the weapon origin
	if ( pPlayer )
	{
		C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
		if ( pLocalPlayer != pPlayer || ::input->CAM_IsThirdPerson() )
		{
			if ( pPlayer->GetActiveWeapon() )
			{
				pPlayer->GetActiveWeapon()->GetAttachment( "muzzle", *vecSrc );
			}
		}
		else
		{
			C_BaseEntity *pViewModel = pLocalPlayer->GetViewModel();

			if ( pViewModel )
			{
				QAngle vecAngles;
				int iMuzzleFlashAttachment = pViewModel->LookupAttachment( "muzzle" );
				pViewModel->GetAttachment( iMuzzleFlashAttachment, *vecSrc, vecAngles );

				Vector vForward;
				AngleVectors( vecAngles, &vForward );

				trace_t trace;	
				UTIL_TraceLine( *vecSrc + vForward * -50, *vecSrc, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace );

				*vecSrc = trace.endpos;
			}
		}
	}
#endif

	// Find angles that will get us to our desired end point
	// Only use the trace end if it wasn't too close, which results
	// in visually bizarre forward angles
	if ( tr.fraction > 0.1 )
	{
		VectorAngles( tr.endpos - *vecSrc, *angForward );
	}
	else
	{
		VectorAngles( endPos - *vecSrc, *angForward );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_FuncPhysicsRespawnZone::RespawnProps( void )
{
	for ( int i = 0; i < m_PropList.Count(); i++ )
	{
		if ( m_PropList[i].hClientEntity == INVALID_CLIENTENTITY_HANDLE )
		{
			if ( !CanMovePropAt( m_PropList[i].vecOrigin, -Vector(32,32,32), Vector(32,32,32) ) )
				continue;

			// This is a crappy way to do this
			C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew();
			if ( pEntity )
			{
				pEntity->m_spawnflags = m_PropList[i].iSpawnFlags;
				pEntity->SetModelName( m_PropList[i].iszModelName );
				pEntity->SetAbsOrigin( m_PropList[i].vecOrigin );
				pEntity->SetAbsAngles( m_PropList[i].vecAngles );
				pEntity->SetPhysicsMode( PHYSICS_MULTIPLAYER_CLIENTSIDE );
				pEntity->m_nSkin = m_PropList[i].iSkin;
				pEntity->m_iHealth = m_PropList[i].iHealth;
				if ( pEntity->m_iHealth == 0 )
				{
					pEntity->m_takedamage = DAMAGE_NO;
				}

				if ( !pEntity->Initialize() )
				{
					pEntity->Release();
				}
				else
				{
					pEntity->SetRespawnZone( this );
					m_PropList[i].hClientEntity = pEntity->GetClientHandle();
				}
			}
		}
		else
		{
			// If the prop has moved, bring it back
			C_BaseEntity *pEntity = ClientEntityList().GetBaseEntityFromHandle( m_PropList[i].hClientEntity );
			if ( pEntity )
			{
				if ( !CollisionProp()->IsPointInBounds( pEntity->WorldSpaceCenter() ) )
				{
					Vector vecMins, vecMaxs;
					pEntity->CollisionProp()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs );
					if ( !CanMovePropAt( m_PropList[i].vecOrigin, vecMins, vecMaxs ) || 
						 !CanMovePropAt( pEntity->GetAbsOrigin(), vecMins, vecMaxs ) )
						continue;

					pEntity->SetAbsOrigin( m_PropList[i].vecOrigin );
					pEntity->SetAbsAngles( m_PropList[i].vecAngles );

					IPhysicsObject *pPhys = pEntity->VPhysicsGetObject();
					if ( pPhys )
					{
						pPhys->SetPosition( pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), true );
					}
				}
			}
		}
	}
}
Example #22
0
void CASWHudUseArea::Paint()
{
	VPROF_BUDGET( "CASWHudUseArea::Paint", VPROF_BUDGETGROUP_ASW_CLIENT );
	GetSize(m_iFrameWidth,m_iFrameHeight);
	m_iFrameWidth = ScreenWidth();
	BaseClass::Paint();

	C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
	if (!pPlayer)
		return;

	C_ASW_Marine *pMarine = pPlayer->GetMarine();
	if (!pMarine)
		return;
	int r, g, b;
	r = g = b = 255;
	if (asw_debug_hud.GetBool())
	{
		char cbuffer[20];
		Q_snprintf(cbuffer, sizeof(cbuffer), "Usable = %d", pPlayer->m_iUseEntities);		
		g_pMatSystemSurface->DrawColoredText(m_hUseAreaFont, 0, 0, r, g, 
				b, 200, &cbuffer[0]);
	}
	
	for (int k=0; k<3; k++)
	{
		pPlayer->UseIconTarget[k] = NULL;
	}

	m_iNumUseIcons = 0;
	pPlayer->FindUseEntities();

	// don't add any icons if our marine is dead
	if (!pPlayer->GetMarine() || !pPlayer->GetMarine()->IsAlive())
	{
		pPlayer->UseIconTarget[0] = NULL;
		if (m_pUseIcon)
			m_pUseIcon->ClearUseAction();
		return;
	}

	int iNumToDraw = MIN(1, pPlayer->m_iUseEntities);
	int iDrew = 0;
	for (int i=0; i<iNumToDraw; i++)
	{	
		if (AddUseIconsFor(pPlayer->GetUseEntity(i)))
			iDrew++;
		
		if (asw_debug_hud.GetBool())
		{
			char buffer[20];
			C_BaseEntity *pEnt = pPlayer->GetUseEntity(i);
			Q_snprintf(buffer, sizeof(buffer), "Use:%d", pEnt->entindex());
			//int wide = g_pMatSystemSurface->DrawTextLen(m_hUseAreaFont, &buffer[0]);
			int tall = vgui::surface()->GetFontTall( m_hUseAreaFont );
			float xPos		= 0;
			float yPos		= (i+1) * tall;
			
			// actual text
			g_pMatSystemSurface->DrawColoredText(m_hUseAreaFont, xPos, yPos, r, g, 
				b, 200, &buffer[0]);
		}
	}
	if (iDrew < 1)
	{
		if (m_pUseIcon)
			m_pUseIcon->ClearUseAction();
	}
}
Example #23
0
//-----------------------------------------------------------------------------
// Sets up the view parameters
//-----------------------------------------------------------------------------
void CViewRender::SetUpView()
{
    VPROF("CViewRender::SetUpView");
    // Initialize view structure with default values
    float farZ = GetZFar();

    m_View.zFar				= farZ;
    m_View.zFarViewmodel	= farZ;
    // UNDONE: Make this farther out?
    //  closest point of approach seems to be view center to top of crouched box
    m_View.zNear			= GetZNear();
    m_View.zNearViewmodel	= 1;
    m_View.fov				= default_fov.GetFloat();

    m_View.m_bOrtho			= false;

    // Enable spatial partition access to edicts
    partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );

    C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

    if ( engine->IsHLTV() )
    {
        HLTVCamera()->CalcView( m_View.origin, m_View.angles, m_View.fov );
    }
    else
    {
        // FIXME: Are there multiple views? If so, then what?
        // FIXME: What happens when there's no player?
        if (pPlayer)
        {
            pPlayer->CalcView( m_View.origin, m_View.angles, m_View.zNear, m_View.zFar, m_View.fov );

            // If we are looking through another entities eyes, then override the angles/origin for m_View
            int viewentity = render->GetViewEntity();

            if ( !g_nKillCamMode && (pPlayer->entindex() != viewentity) )
            {
                C_BaseEntity *ve = cl_entitylist->GetEnt( viewentity );
                if ( ve )
                {
                    VectorCopy( ve->GetAbsOrigin(), m_View.origin );
                    VectorCopy( ve->GetAbsAngles(), m_View.angles );
                }
            }

            pPlayer->CalcViewModelView( m_View.origin, m_View.angles );
        }

        // Even if the engine is paused need to override the view
        // for keeping the camera control during pause.
        g_pClientMode->OverrideView( &m_View );
    }

    // give the toolsystem a chance to override the view
    ToolFramework_SetupEngineView( m_View.origin, m_View.angles, m_View.fov );

    if ( engine->IsPlayingDemo() )
    {
        if ( cl_demoviewoverride.GetFloat() > 0.0f )
        {
            // Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
            CalcDemoViewOverride( m_View.origin, m_View.angles );
        }
        else
        {
            s_DemoView = m_View.origin;
            s_DemoAngle = m_View.angles;
        }
    }

    //Find the offset our current FOV is from the default value
    float flFOVOffset = default_fov.GetFloat() - m_View.fov;

    //Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
    m_View.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;

    // Disable spatical partition access
    partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );

    // Enable access to all model bones
    C_BaseAnimating::PopBoneAccess( "OnRenderStart->CViewRender::SetUpView" ); // pops the (true, false) bone access set in OnRenderStart
    C_BaseAnimating::PushAllowBoneAccess( true, true, "CViewRender::SetUpView->OnRenderEnd" ); // pop is in OnRenderEnd()

    // Compute the world->main camera transform
    ComputeCameraVariables( m_View.origin, m_View.angles,
                            &g_vecVForward, &g_vecVRight, &g_vecVUp, &g_matCamInverse );

    // set up the hearing origin...
    AudioState_t audioState;
    audioState.m_Origin = m_View.origin;
    audioState.m_Angles = m_View.angles;
    audioState.m_bIsUnderwater = pPlayer && pPlayer->AudioStateIsUnderwater( m_View.origin );

    ToolFramework_SetupAudioState( audioState );

    m_View.origin = audioState.m_Origin;
    m_View.angles = audioState.m_Angles;

    engine->SetAudioState( audioState );

    g_vecPrevRenderOrigin = g_vecRenderOrigin;
    g_vecPrevRenderAngles = g_vecRenderAngles;
    g_vecRenderOrigin = m_View.origin;
    g_vecRenderAngles = m_View.angles;

#ifdef _DEBUG
    s_DbgSetupOrigin = m_View.origin;
    s_DbgSetupAngles = m_View.angles;
#endif
}
Example #24
0
void CPDumpPanel::Paint()
{
	C_BaseEntity *ent = m_hDumpEntity;
	if ( !ent )
	{
		Clear();
		return;
	}

	// Now output the strings
	int x[5];
	x[0] = 20;
	int columnwidth = 375;
	int numcols = ScreenWidth() / columnwidth;
	int i;

	numcols = clamp( numcols, 1, 5 );

	for ( i = 0; i < numcols; i++ )
	{
		if ( i == 0 )
		{
			x[i] = 20;
		}
		else
		{
			x[i] = x[ i-1 ] + columnwidth - 20;
		}
	}

	int c = m_DumpEntityInfo.Size();
	int fonttall = vgui::surface()->GetFontTall( m_FontSmall ) - 3;
	int fonttallMedium = vgui::surface()->GetFontTall( m_FontMedium );
	int fonttallBig = vgui::surface()->GetFontTall( m_FontBig );

	char currentclass[ 128 ];
	currentclass[ 0 ] = 0;

	int starty = 60;
	int y = starty;

	int col = 0;

	int r = 255;
	int g = 255;
	int b = 255;
	int a = 255;

	char classextra[ 32 ];
	classextra[ 0 ] = 0;
	char classprefix[ 32 ];
	Q_strncpy( classprefix, "class ", sizeof( classprefix ) );
	const char *classname = ent->GetClassname();
	if ( !classname[ 0 ] )
	{
		classname = typeid( *ent ).name();
		Q_strncpy( classextra, " (classmap missing)", sizeof( classextra ) );
		classprefix[ 0 ] = 0;
	}

	char sz[ 512 ];
	wchar_t szconverted[ 1024 ];

	surface()->DrawSetTextFont( m_FontBig );
	surface()->DrawSetTextColor( Color( 255, 255, 255, 255 ) );
	surface()->DrawSetTextPos( x[ col ] - 10, y - fonttallBig - 2 );
	Q_snprintf( sz, sizeof( sz ), "entity # %i: %s%s%s", ent->entindex(), classprefix, classname, classextra );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	for ( i = 0; i < c; i++ )
	{
		DumpInfo *slot = &m_DumpEntityInfo[ i ];

		if ( stricmp( slot->classname, currentclass ) )
		{
			y += 2;

			surface()->DrawSetTextFont( m_FontMedium );
			surface()->DrawSetTextColor( Color( 0, 255, 100, 255 ) );
			surface()->DrawSetTextPos( x[ col ] - 10, y );
			Q_snprintf( sz, sizeof( sz ), "%s", slot->classname );
			g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
			surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

			y += fonttallMedium-1;
			Q_strncpy( currentclass, slot->classname, sizeof( currentclass ) );
		}

	
		PredictionDumpColor( slot->networked, !slot->noterrorchecked, slot->differs, slot->withintolerance,
			r, g, b, a );

		surface()->DrawSetTextFont( m_FontSmall );
		surface()->DrawSetTextColor( Color( r, g, b, a ) );
		surface()->DrawSetTextPos( x[ col ], y );
		Q_snprintf( sz, sizeof( sz ), "%s", slot->fieldstring );
		g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
		surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

		y += fonttall;

		if ( y >= ScreenHeight() - fonttall - 60 )
		{
			y = starty;
			col++;
			if ( col >= numcols )
				break;
		}
	}

	surface()->DrawSetTextFont( m_FontSmall );


	// Figure how far over the legend needs to be.
	const char *pFirstAndLongestString = "Not networked, no differences";
	g_pVGuiLocalize->ConvertANSIToUnicode( pFirstAndLongestString, szconverted, sizeof(szconverted)  );
	int textSizeWide, textSizeTall;
	surface()->GetTextSize( m_FontSmall, szconverted, textSizeWide, textSizeTall );


	// Draw a legend now
	int xpos = ScreenWidth() - textSizeWide - 5;
	y = ScreenHeight() - 7 * fonttall - 80;

	// Not networked, no differences
	PredictionDumpColor( false, false, false, false, r, g, b, a );


	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, pFirstAndLongestString, sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;

	// Networked, no error check
	PredictionDumpColor( true, false, false, false, r, g, b, a );

	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, "Networked, not checked", sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;

	// Networked, with error check
	PredictionDumpColor( true, true, false, false, r, g, b, a );

	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, "Networked, error checked", sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;

	// Differs, but within tolerance
	PredictionDumpColor( true, true, true, true, r, g, b, a );

	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, "Differs, but within tolerance", sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;

	// Differs, not within tolerance, but not networked
	PredictionDumpColor( false, true, true, false, r, g, b, a );

	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, "Differs, but not networked", sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;

	// Differs, networked, not within tolerance
	PredictionDumpColor( true, true, true, false, r, g, b, a );

	surface()->DrawSetTextColor( Color( r, g, b, a ) );
	surface()->DrawSetTextPos( xpos, y );
	Q_strncpy( sz, "Differs, networked", sizeof( sz ) );
	g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted)  );
	surface()->DrawPrintText( szconverted, wcslen( szconverted ) );

	y += fonttall;
}
Example #25
0
void CBasePlayerAnimState::Update( float eyeYaw, float eyePitch )
{
	VPROF( "CBasePlayerAnimState::Update" );

	// Clear animation overlays because we're about to completely reconstruct them.
	ClearAnimationLayers();

	// Some mods don't want to update the player's animation state if they're dead and ragdolled.
	if ( !ShouldUpdateAnimState() )
	{
		ClearAnimationState();
		return;
	}
	
	
	CStudioHdr *pStudioHdr = GetOuter()->GetModelPtr();
	// Store these. All the calculations are based on them.
	m_flEyeYaw = AngleNormalize( eyeYaw );
	m_flEyePitch = AngleNormalize( eyePitch );

	// Compute sequences for all the layers.
	ComputeSequences( pStudioHdr );
	
	
	// Compute all the pose params.
	ComputePoseParam_BodyPitch( pStudioHdr );	// Look up/down.
	ComputePoseParam_BodyYaw();		// Torso rotation.
	ComputePoseParam_MoveYaw( pStudioHdr );		// What direction his legs are running in.

	
	ComputePlaybackRate();


#ifdef CLIENT_DLL
	if ( cl_showanimstate.GetInt() == m_pOuter->entindex() )
	{
		DebugShowAnimStateFull( 5 );
	}
	else if ( cl_showanimstate.GetInt() == -2 )
	{
		C_BasePlayer *targetPlayer = C_BasePlayer::GetLocalPlayer();

		if( targetPlayer && ( targetPlayer->GetObserverMode() == OBS_MODE_IN_EYE || targetPlayer->GetObserverMode() == OBS_MODE_CHASE ) )
		{
			C_BaseEntity *target = targetPlayer->GetObserverTarget();

			if( target && target->IsPlayer() )
			{
				targetPlayer = ToBasePlayer( target );
			}
		}

		if ( m_pOuter == targetPlayer )
		{
			DebugShowAnimStateFull( 6 );
		}
	}
#else
	if ( sv_showanimstate.GetInt() == m_pOuter->entindex() )
	{
		DebugShowAnimState( 20 );
	}
#endif
}
Example #26
0
void CPhysicsSystem::PhysicsSimulate()
{
	CMiniProfilerGuard mpg(&g_mp_PhysicsSimulate);
	VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS );
	float frametime = gpGlobals->frametime;

	if ( physenv )
	{
		g_Collisions.BufferTouchEvents( true );
#ifdef _DEBUG
		physenv->DebugCheckContacts();
#endif
		frametime *= cl_phys_timescale.GetFloat();

		int maxTicks = cl_phys_maxticks.GetInt();
		if ( maxTicks )
		{
			float maxFrameTime = physenv->GetDeltaFrameTime( maxTicks ) - 1e-4f;
			frametime = clamp( frametime, 0, maxFrameTime );
		}

		physenv->Simulate( frametime );

		int activeCount = physenv->GetActiveObjectCount();
		g_mp_active_object_count.Add(activeCount);
		IPhysicsObject **pActiveList = NULL;
		if ( activeCount )
		{
			PHYS_PROFILE(aUpdateActiveObjects)
			pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount );
			physenv->GetActiveObjects( pActiveList );

			for ( int i = 0; i < activeCount; i++ )
			{
				C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData());
				if ( pEntity )
				{
					//const CCollisionProperty *collProp = pEntity->CollisionProp();
					//debugoverlay->AddBoxOverlay( collProp->GetCollisionOrigin(), collProp->OBBMins(), collProp->OBBMaxs(), collProp->GetCollisionAngles(), 190, 190, 0, 0, 0.01 );

					if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() )
					{
						pEntity->CollisionProp()->MarkSurroundingBoundsDirty();
					}
					pEntity->VPhysicsUpdate( pActiveList[i] );
					IPhysicsShadowController *pShadow = pActiveList[i]->GetShadowController();
					if ( pShadow )
					{
						// active shadow object, check for error
						Vector pos, targetPos;
						QAngle rot, targetAngles;
						pShadow->GetTargetPosition( &targetPos, &targetAngles );
						pActiveList[i]->GetPosition( &pos, &rot );
						Vector delta = targetPos - pos;
						float dist = VectorNormalize(delta);
						bool bBlocked = false;
						if ( dist > cl_phys_block_dist.GetFloat() )
						{
							Vector vel;
							pActiveList[i]->GetImplicitVelocity( &vel, NULL );
							float proj = DotProduct(vel, delta);
							if ( proj < dist * cl_phys_block_fraction.GetFloat() )
							{
								bBlocked = true;
								//Msg("%s was blocked %.3f (%.3f proj)!\n", pEntity->GetClassname(), dist, proj );
							}
						}
						Vector targetAxis;
						float deltaTargetAngle;
						RotationDeltaAxisAngle( rot, targetAngles, targetAxis, deltaTargetAngle );
						if ( fabsf(deltaTargetAngle) > 0.5f )
						{
							AngularImpulse angVel;
							pActiveList[i]->GetImplicitVelocity( NULL, &angVel );
							float proj = DotProduct( angVel, targetAxis ) * Sign(deltaTargetAngle);
							if ( proj < (fabsf(deltaTargetAngle) * cl_phys_block_fraction.GetFloat()) )
							{
								bBlocked = true;
								//Msg("%s was rot blocked %.3f proj %.3f!\n", pEntity->GetClassname(), deltaTargetAngle, proj );
							}
						}
					
						if ( bBlocked )
						{
							C_BaseEntity *pBlocker = FindPhysicsBlocker( pActiveList[i] );
							if ( pBlocker )
							{
								if ( IsBlockedShouldDisableCollisions( pEntity ) )
								{
									PhysDisableEntityCollisions( pEntity, pBlocker );
									pActiveList[i]->RecheckContactPoints();
									// GetClassname returns a pointer to the same buffer always!
									//Msg("%s blocked !", pEntity->GetClassname() ); Msg("by %s\n", pBlocker->GetClassname() );
								}
							}
						}
					}
				}
			}
		}

#if 0
		if ( cl_visualize_physics_shadows.GetBool() )
		{
			int entityCount = NUM_ENT_ENTRIES;
			for ( int i = 0; i < entityCount; i++ )
			{
				IClientEntity *pClientEnt = cl_entitylist->GetClientEntity(i);
				if ( !pClientEnt )
					continue;
				C_BaseEntity *pEntity = pClientEnt->GetBaseEntity();
				if ( !pEntity )
					continue;

				Vector pos;
				QAngle angle;
				IPhysicsObject *pObj = pEntity->VPhysicsGetObject();
				if ( !pObj || !pObj->GetShadowController() )
					continue;

				pObj->GetShadowPosition( &pos, &angle );
				debugoverlay->AddBoxOverlay( pos, pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), angle, 255, 255, 0, 32, 0 );
				char tmp[256];
				V_snprintf( tmp, sizeof(tmp),"%s, (%s)\n", pEntity->GetClassname(), VecToString(angle) );
				debugoverlay->AddTextOverlay( pos, 0, tmp );
			}
		}
#endif
		g_Collisions.BufferTouchEvents( false );
		g_Collisions.FrameUpdate();
	}
	physicssound::PlayImpactSounds( m_impactSounds );
}
//-----------------------------------------------------------------------------
// helper for traversing ownership hierarchy
//-----------------------------------------------------------------------------
EntitySearchResult CClientTools::GetOwnerEntity( EntitySearchResult currentEnt )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity* >( currentEnt );
	return ent ? ent->GetOwnerEntity() : NULL;
}
Example #28
0
//======================================================================================================================
// PARTICLE SYSTEM DISPATCH EFFECT
//======================================================================================================================
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void StartParticleEffect( const CEffectData &data, int nSplitScreenPlayerSlot /*= -1*/ )
{
	// this needs to be before using data.m_nHitBox, 
	// since that may be a serialized value that's past the end of the current particle system string table
	if ( SuppressingParticleEffects() )
		return; 

	// Don't crash if we're passed an invalid particle system
	if ( data.m_nHitBox == 0 )
		return;

	if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY )
	{
		if ( data.m_hEntity.Get() )
		{
			C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
			// commented out assert. dormant entities have their particle system spawns stopped.
			//Assert( pEnt && !pEnt->IsDormant() );
			if ( pEnt && !pEnt->IsDormant() )
			{
				if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES )
				{
					pEnt->ParticleProp()->StopEmission();
				}

				CUtlReference<CNewParticleEffect> pEffect = pEnt->ParticleProp()->CreatePrecached( data.m_nHitBox, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex );

				if ( pEffect.IsValid() && pEffect->IsValid() )
				{
					if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN || (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN_FOLLOW )
					{
						pEffect->SetDrawOnlyForSplitScreenUser( nSplitScreenPlayerSlot );
						pEffect->SetSortOrigin( data.m_vOrigin );
						if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN_FOLLOW )
						{
							Vector vecCtrl1 = (data.m_vStart - pEnt->GetAbsOrigin() );
							pEffect->SetControlPoint( 1, vecCtrl1 );
							pEffect->SetControlPointEntity( 1, pEnt );
							Vector vecCtrl0 = (data.m_vOrigin - pEnt->GetAbsOrigin() );
							matrix3x4_t mat;
							AngleMatrix( data.m_vAngles, mat );
							pEnt->ParticleProp()->AddControlPoint( pEffect, 0, pEnt, PATTACH_CUSTOMORIGIN_FOLLOW, NULL, vecCtrl0, &mat );
						}
						else
						{
							pEffect->SetControlPoint( 0, data.m_vOrigin );
							pEffect->SetControlPoint( 1, data.m_vStart );
							Vector vecForward, vecRight, vecUp;
							AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp );
							pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
						}
					}
					else if ( data.m_nOtherEntIndex > 0 )
					{
						C_BaseEntity *pOtherEnt = ClientEntityList().GetEnt( data.m_nOtherEntIndex );
					
						if ( pOtherEnt )
						{
							pEnt->ParticleProp()->AddControlPoint( pEffect, 1, pOtherEnt, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector( 0, 0, 50 ) );
						}
					}
				}
			}
		}
	}	
	else
	{
		CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindPrecachedParticleSystem( data.m_nHitBox );
		if ( pDef )
		{
			CUtlReference<CNewParticleEffect> pEffect = CNewParticleEffect::CreateOrAggregate( NULL, pDef, data.m_vOrigin, NULL, nSplitScreenPlayerSlot );
			if ( pEffect.IsValid() && pEffect->IsValid() )
			{
				pEffect->SetSortOrigin( data.m_vOrigin );
				pEffect->SetControlPoint( 0, data.m_vOrigin );
				pEffect->SetControlPoint( 1, data.m_vStart );
				Vector vecForward, vecRight, vecUp;
				AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp );
				pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
			}
		}
		else
		{
			Warning( "StartParticleEffect:  Failed to find precached particle system for %d!!\n", data.m_nHitBox );
		}
	}
}
Example #29
0
//-----------------------------------------------------------------------------
// Sets up the view parameters
//-----------------------------------------------------------------------------
void CViewRender::SetUpViews()
{
	VPROF("CViewRender::SetUpViews");

	// Initialize view structure with default values
	float farZ = GetZFar();

    // Set up the mono/middle view.
    CViewSetup &view = m_View;

	view.zFar				= farZ;
	view.zFarViewmodel	    = farZ;
	// UNDONE: Make this farther out? 
	//  closest point of approach seems to be view center to top of crouched box
	view.zNear			    = GetZNear();
	view.zNearViewmodel	    = 1;
	view.fov				= default_fov.GetFloat();

	view.m_bOrtho			= false;
    view.m_bViewToProjectionOverride = false;
	view.m_eStereoEye		= STEREO_EYE_MONO;

	// Enable spatial partition access to edicts
	partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );

	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();

	// You in-view weapon aim.
	bool bCalcViewModelView = false;
	Vector ViewModelOrigin;
	QAngle ViewModelAngles;

	if ( engine->IsHLTV() )
	{
		HLTVCamera()->CalcView( view.origin, view.angles, view.fov );
	}
#if defined( REPLAY_ENABLED )
	else if ( g_pEngineClientReplay->IsPlayingReplayDemo() )
	{
		ReplayCamera()->CalcView( view.origin, view.angles, view.fov );
	}
#endif
	else
	{
		// FIXME: Are there multiple views? If so, then what?
		// FIXME: What happens when there's no player?
		if (pPlayer)
		{
			pPlayer->CalcView( view.origin, view.angles, view.zNear, view.zFar, view.fov );

			// If we are looking through another entities eyes, then override the angles/origin for view
			int viewentity = render->GetViewEntity();

			if ( !g_nKillCamMode && (pPlayer->entindex() != viewentity) )
			{
				C_BaseEntity *ve = cl_entitylist->GetEnt( viewentity );
				if ( ve )
				{
					VectorCopy( ve->GetAbsOrigin(), view.origin );
					VectorCopy( ve->GetAbsAngles(), view.angles );
				}
			}

			// There is a viewmodel.
			bCalcViewModelView = true;
			ViewModelOrigin = view.origin;
			ViewModelAngles = view.angles;
		}
		else
		{
			view.origin.Init();
			view.angles.Init();
		}

		// Even if the engine is paused need to override the view
		// for keeping the camera control during pause.
		g_pClientMode->OverrideView( &view );
	}

	// give the toolsystem a chance to override the view
	ToolFramework_SetupEngineView( view.origin, view.angles, view.fov );

	if ( engine->IsPlayingDemo() )
	{
		if ( cl_demoviewoverride.GetFloat() > 0.0f )
		{
			// Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
			CalcDemoViewOverride( view.origin, view.angles );
		}
		else
		{
			s_DemoView = view.origin;
			s_DemoAngle = view.angles;
		}
	}

	//Find the offset our current FOV is from the default value
	float fDefaultFov = default_fov.GetFloat();
	float flFOVOffset = fDefaultFov - view.fov;

	//Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
	view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;

	if ( UseVR() )
	{
		// Let the headtracking read the status of the HMD, etc.
		// This call can go almost anywhere, but it needs to know the player FOV for sniper weapon zoom, etc
		if ( flFOVOffset == 0.0f )
		{
			g_ClientVirtualReality.ProcessCurrentTrackingState ( 0.0f );
		}
		else
		{
			g_ClientVirtualReality.ProcessCurrentTrackingState ( view.fov );
		}

		HeadtrackMovementMode_t hmmOverrideMode = g_pClientMode->ShouldOverrideHeadtrackControl();
		g_ClientVirtualReality.OverrideView( &m_View, &ViewModelOrigin, &ViewModelAngles, hmmOverrideMode );

		// left and right stereo views should default to being the same as the mono/middle view
		m_ViewLeft = m_View;
		m_ViewRight = m_View;
		m_ViewLeft.m_eStereoEye = STEREO_EYE_LEFT;
		m_ViewRight.m_eStereoEye = STEREO_EYE_RIGHT;

		g_ClientVirtualReality.OverrideStereoView( &m_View, &m_ViewLeft, &m_ViewRight );
	}
	else
	{
		// left and right stereo views should default to being the same as the mono/middle view
		m_ViewLeft = m_View;
		m_ViewRight = m_View;
		m_ViewLeft.m_eStereoEye = STEREO_EYE_LEFT;
		m_ViewRight.m_eStereoEye = STEREO_EYE_RIGHT;
	}

	if ( bCalcViewModelView )
	{
		Assert ( pPlayer != NULL );
		pPlayer->CalcViewModelView ( ViewModelOrigin, ViewModelAngles );
	}

	// Disable spatial partition access
	partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );

	// Enable access to all model bones
	C_BaseAnimating::PopBoneAccess( "OnRenderStart->CViewRender::SetUpView" ); // pops the (true, false) bone access set in OnRenderStart
	C_BaseAnimating::PushAllowBoneAccess( true, true, "CViewRender::SetUpView->OnRenderEnd" ); // pop is in OnRenderEnd()

	// Compute the world->main camera transform
    // This is only done for the main "middle-eye" view, not for the various other views.
	ComputeCameraVariables( view.origin, view.angles, 
		&g_vecVForward, &g_vecVRight, &g_vecVUp, &g_matCamInverse );

	// set up the hearing origin...
	AudioState_t audioState;
	audioState.m_Origin = view.origin;
	audioState.m_Angles = view.angles;
	audioState.m_bIsUnderwater = pPlayer && pPlayer->AudioStateIsUnderwater( view.origin );

	ToolFramework_SetupAudioState( audioState );

    // TomF: I wonder when the audio tools modify this, if ever...
    Assert ( view.origin == audioState.m_Origin );
    Assert ( view.angles == audioState.m_Angles );
	view.origin = audioState.m_Origin;
	view.angles = audioState.m_Angles;

	engine->SetAudioState( audioState );

	g_vecPrevRenderOrigin = g_vecRenderOrigin;
	g_vecPrevRenderAngles = g_vecRenderAngles;
	g_vecRenderOrigin = view.origin;
	g_vecRenderAngles = view.angles;

#ifdef DBGFLAG_ASSERT
	s_DbgSetupOrigin = view.origin;
	s_DbgSetupAngles = view.angles;
#endif
}
void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
	m_pParticleMgr = pParticleMgr;
	if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
		return;

	if (!m_szMaterialName[0])
	{
		strcpy(m_szMaterialName, "particle/particle_noisesphere");
	}

	m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);

	// Precalculate stuff for the particle spawning..
	#define NUM_DUSTEMITTER_SURFINFOS	128
	SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
	int nSurfInfos;

	// Center of explosion.
	Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.

	
	#ifdef PARTICLEPROTOTYPE_APP
		float surfSize = 10000;
		nSurfInfos = 1;
		surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
		surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
		surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
		surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
		surfInfos[0].m_nVerts = 4;
		surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
		surfInfos[0].m_Plane.m_Dist = -3;
	#else
		{
			nSurfInfos = 0;
			C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
			if ( ent )
			{
				nSurfInfos = engine->GetIntersectingSurfaces(
					ent->GetModel(),
					vCenter,
					AR2_DUST_RADIUS,
					true,
					surfInfos,
					NUM_DUSTEMITTER_SURFINFOS);
			}
		}
	#endif

	int nParticles = 0;

	if(nSurfInfos > 0)
	{
		// For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
		int nTestsPerParticle=3;
		for(int i=0; i < NUM_AR2_EXPLOSION_PARTICLES; i++)
		{
			for(int iTest=0; iTest < nTestsPerParticle; iTest++)
			{
				Vector randVec = RandomVector(-1,1);
				VectorNormalize( randVec );
				Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;

				randVec = RandomVector(-1,1);
				VectorNormalize( randVec );
				Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;

				#define MAX_SURFINFO_INTERSECTIONS	4
				SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
				Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
				int nIntersections;
				nIntersections = IntersectSegmentWithSurfInfos(
					startPos, 
					endPos, 
					surfInfos, 
					nSurfInfos, 
					pIntersected,
					vIntersections,
					MAX_SURFINFO_INTERSECTIONS);
				
				if(nIntersections)
				{
					int iIntersection = rand() % nIntersections;

					Vector velocity;
					//velocity.Init(-1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f);
					//velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
					Vector direction = (vIntersections[iIntersection] - vCenter );
					float dist = VectorNormalize( direction );
					if(dist > AR2_DUST_RADIUS)
						dist = AR2_DUST_RADIUS;

					static float power = 2.0f;
					float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);

					Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
					VectorNormalize( reflection );

					velocity = reflection * AR2_DUST_SPEED * falloffMul;
					// velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;

					
					/*
					debugoverlay->AddLineOverlay( vIntersections[iIntersection], 
												  vIntersections[iIntersection] + reflection * 64,
												  128, 128, 255, false, 15.0 );
					*/
#if 1
					AR2ExplosionParticle *pParticle = 
						(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );

					if(pParticle)
					{
						pParticle->m_Pos = vIntersections[iIntersection];
						pParticle->m_Start = pParticle->m_Pos;
						pParticle->m_Dist = 8.0;
						pParticle->m_Velocity = velocity;
						// sound == 13031.496062992125984251968503937ips
						pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
						pParticle->m_Roll = FRand( 0, M_PI * 2 );
						pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
						pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
						nParticles++;
						break;
					}
#endif
				}
			}
		}
	}	

	// build interior smoke particles
	for(int i=nParticles; i < NUM_AR2_EXPLOSION_PARTICLES; i++)
	{
		Vector randVec = RandomVector(-1,1);
		VectorNormalize( randVec );
		Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;

		Vector direction = (endPos - vCenter );
		float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
		if(dist > AR2_DUST_RADIUS)
			dist = AR2_DUST_RADIUS;

		static float power = 2.0f;
		float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);

		Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
		AR2ExplosionParticle *pParticle = 
			(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );

		if(pParticle)
		{
			pParticle->m_Pos = endPos;
			pParticle->m_Start = pParticle->m_Pos;
			pParticle->m_Dist = 8.0;
			pParticle->m_Velocity = velocity;
			// sound == 13031.496062992125984251968503937ips
			pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
			pParticle->m_Roll = FRand( 0, M_PI * 2 );
			pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
			pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
		}
	}
}