void CClientTools::SetRenderGroup( IClientRenderable *pRenderable, int renderGroup )
{
	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	if ( INVALID_CLIENT_RENDER_HANDLE == handle )
	{
		// create new renderer handle
		ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup );
	}
	else
	{
		// handle already exists, just update group & origin
		ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup );
		ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
	}
}
void CNewParticleEffect::DetectChanges()
{
	// if we have no render handle, return
	if ( m_hRenderHandle == INVALID_CLIENT_RENDER_HANDLE )
		return;

	// Turn off rendering if the bounds aren't valid
	g_pClientLeafSystem->EnableRendering( m_hRenderHandle, m_bBoundsValid );

	if ( !m_bBoundsValid )
	{
		m_LastMin.Init( FLT_MAX, FLT_MAX, FLT_MAX );
		m_LastMin.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );
		return;
	}

	if ( m_MinBounds != m_LastMin || m_MaxBounds != m_LastMax ) 
	{
		// call leafsystem to update this guy
		ClientLeafSystem()->RenderableChanged( m_hRenderHandle );

		// remember last parameters
		m_LastMin = m_MinBounds;
		m_LastMax = m_MaxBounds;
	}
}
void CClientTools::RemoveClientRenderable( IClientRenderable *pRenderable )
{
	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	if( handle != INVALID_CLIENT_RENDER_HANDLE )
	{
		ClientLeafSystem()->RemoveRenderable( handle );
	}
	cl_entitylist->RemoveEntity( pRenderable->GetIClientUnknown()->GetRefEHandle() );
}
void CClientTools::MarkClientRenderableDirty( IClientRenderable *pRenderable )
{
	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	if ( INVALID_CLIENT_RENDER_HANDLE != handle )
	{
		// handle already exists, just update group & origin
		ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
	}
}
示例#5
0
//-----------------------------------------------------------------------------
// Purpose: Updates the envelope being in the client's known entity list
//-----------------------------------------------------------------------------
void C_EnvelopeFX::Update( void )
{
	if ( m_active )
	{
		if ( m_hRenderHandle == INVALID_CLIENT_RENDER_HANDLE )
		{
			ClientLeafSystem()->AddRenderable( this, RENDER_GROUP_TRANSLUCENT_ENTITY );
		}
		else
		{
			ClientLeafSystem()->RenderableChanged( m_hRenderHandle );
		}
	}
	else
	{
		RemoveRenderable();
	}
}
void C_BeamQuadratic::Update( C_BaseEntity *pOwner )
{
	m_pOwner = pOwner;
	if ( m_active )
	{
		if ( m_hRenderHandle == INVALID_CLIENT_RENDER_HANDLE )
		{
			ClientLeafSystem()->AddRenderable( this, RENDER_GROUP_TRANSLUCENT_ENTITY );
		}
		else
		{
			ClientLeafSystem()->RenderableChanged( m_hRenderHandle );
		}
	}
	else if ( !m_active && m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE )
	{
		ClientLeafSystem()->RemoveRenderable( m_hRenderHandle );
	}
}
void CClientTools::AddClientRenderable( IClientRenderable *pRenderable, int renderGroup )
{
	Assert( pRenderable );

	cl_entitylist->AddNonNetworkableEntity( pRenderable->GetIClientUnknown() );

	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	if ( INVALID_CLIENT_RENDER_HANDLE == handle )
	{
		// create new renderer handle
		ClientLeafSystem()->AddRenderable( pRenderable, (RenderGroup_t)renderGroup );
	}
	else
	{
		// handle already exists, just update group & origin
		ClientLeafSystem()->SetRenderGroup( pRenderable->RenderHandle(), (RenderGroup_t)renderGroup );
		ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
	}

}
void CClientTools::AddClientRenderable( IClientRenderable *pRenderable, bool bRenderWithViewModels, RenderableTranslucencyType_t nType, RenderableModelType_t nModelType )
{
	Assert( pRenderable );

	cl_entitylist->AddNonNetworkableEntity( pRenderable->GetIClientUnknown() );

	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	if ( INVALID_CLIENT_RENDER_HANDLE == handle )
	{
		// create new renderer handle
		ClientLeafSystem()->AddRenderable( pRenderable, bRenderWithViewModels, nType, nModelType );
	}
	else
	{
		// handle already exists, just update group & origin
		ClientLeafSystem()->RenderWithViewModels( pRenderable->RenderHandle(), bRenderWithViewModels );
		ClientLeafSystem()->SetTranslucencyType( pRenderable->RenderHandle(), nType );
		ClientLeafSystem()->SetModelType( pRenderable->RenderHandle(), nModelType );
		ClientLeafSystem()->RenderableChanged( pRenderable->RenderHandle() );
	}
}
示例#9
0
// The is the max size of the particles for use in bounding	computation
void CParticleEffectBinding::SetParticleCullRadius( float flMaxParticleRadius )
{
	if ( m_flParticleCullRadius != flMaxParticleRadius )
	{
		m_flParticleCullRadius = flMaxParticleRadius;

		if ( m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE )
		{
			ClientLeafSystem()->RenderableChanged( m_hRenderHandle );
		}
	}
}
void CBulletManager::BulletsThink(float flFrameTime)
{
	for (int i = 0; i < m_aBullets.Count(); i++)
	{
		CBullet& oBullet = m_aBullets[i];
		if (!oBullet.m_bActive)
			continue;

		if (!oBullet.m_hShooter)
			oBullet.Deactivate();

		float flSpeed = da_bullet_speed.GetFloat();
		float flLerpTime = flSpeed / 400 * flFrameTime;

		if (oBullet.m_hShooter)
		{
			if (oBullet.m_hShooter->m_Shared.m_bSuperSkill || oBullet.m_hShooter->GetSlowMoType() == SLOWMO_ACTIVATED || oBullet.m_hShooter->GetSlowMoType() == SLOWMO_STYLESKILL)
				flSpeed = da_bullet_speed_active.GetFloat();

				flLerpTime *= oBullet.m_hShooter->GetSlowMoMultiplier();
		}

		oBullet.m_flCurrAlpha = Approach(oBullet.m_flGoalAlpha, oBullet.m_flCurrAlpha, flLerpTime);

		if (oBullet.m_bActive && oBullet.m_flGoalAlpha == 0 && oBullet.m_flCurrAlpha == 0)
		{
			oBullet.m_bActive = false;
#ifdef CLIENT_DLL
			ClientLeafSystem()->RemoveRenderable( oBullet.m_hRenderHandle );
#endif
			continue;
		}

		if (gpGlobals->curtime > oBullet.m_flShotTime + 10)
		{
			oBullet.Deactivate();
			continue;
		}

		if (!oBullet.m_hShooter)
			continue;

		float dt;
		if (oBullet.m_hShooter->GetSlowMoMultiplier() == 1)
			dt = -1;
		else
			dt = flSpeed * oBullet.m_hShooter->GetSlowMoMultiplier() * flFrameTime;

		SimulateBullet(oBullet, dt);
	}
}
void CBulletManager::CBullet::Activate()
{
	m_bActive = true;

	m_flGoalAlpha = 1;

#ifdef CLIENT_DLL
	if (m_hShooter == C_DAPlayer::GetLocalOrSpectatedPlayer())
		m_flCurrAlpha = -0.3f; // Don't appear until it's a little ways from the player.
	else
		m_flCurrAlpha = 0.0f;
#else
	m_flCurrAlpha = 0;
#endif

#ifdef CLIENT_DLL
	ClientLeafSystem()->AddRenderable( this, RENDER_GROUP_TRANSLUCENT_ENTITY );
#endif
}
void CNewParticleEffect::DetectChanges()
{
	// if we have no render handle, return
	if ( m_hRenderHandle == INVALID_CLIENT_RENDER_HANDLE )
		return;

	float flBuffer = cl_particleeffect_aabb_buffer.GetFloat();
	float flExtraBuffer = flBuffer * 1.3f;

	// if nothing changed, return
	if ( m_MinBounds.x < m_LastMin.x || 
		 m_MinBounds.y < m_LastMin.y || 
		 m_MinBounds.z < m_LastMin.z || 

		 m_MinBounds.x > (m_LastMin.x + flExtraBuffer) ||
		 m_MinBounds.y > (m_LastMin.y + flExtraBuffer) ||
		 m_MinBounds.z > (m_LastMin.z + flExtraBuffer) ||

		 m_MaxBounds.x > m_LastMax.x || 
		 m_MaxBounds.y > m_LastMax.y || 
		 m_MaxBounds.z > m_LastMax.z || 

		 m_MaxBounds.x < (m_LastMax.x - flExtraBuffer) ||
		 m_MaxBounds.y < (m_LastMax.y - flExtraBuffer) ||
		 m_MaxBounds.z < (m_LastMax.z - flExtraBuffer)
		 )
	{
		// call leafsystem to updated this guy
		ClientLeafSystem()->RenderableChanged( m_hRenderHandle );

		// remember last parameters
		// Add some padding in here so we don't reinsert it into the leaf system if it just changes a tiny amount.
		m_LastMin = m_MinBounds - Vector( flBuffer, flBuffer, flBuffer );
		m_LastMax = m_MaxBounds + Vector( flBuffer, flBuffer, flBuffer );
	}
}
示例#13
0
void C_SDKRagdoll::CreateRagdoll()
{
	// First, initialize all our data. If we have the player's entity on our client,
	// then we can make ourselves start out exactly where the player is.
	C_SDKPlayer *pPlayer = dynamic_cast< C_SDKPlayer* >( m_hPlayer.Get() );

	if ( pPlayer && !pPlayer->IsDormant() )
	{
		// move my current model instance to the ragdoll's so decals are preserved.
		pPlayer->SnatchModelInstance( this );

		VarMapping_t *varMap = GetVarMapping();

		// Copy all the interpolated vars from the player entity.
		// The entity uses the interpolated history to get bone velocity.
		if ( !pPlayer->IsLocalPlayer() && pPlayer->IsInterpolationEnabled() )
		{
			Interp_Copy( pPlayer );

			SetAbsAngles( pPlayer->GetRenderAngles() );
			GetRotationInterpolator().Reset();

			m_flAnimTime = pPlayer->m_flAnimTime;
			SetSequence( pPlayer->GetSequence() );
			m_flPlaybackRate = pPlayer->GetPlaybackRate();
		}
		else
		{
			// This is the local player, so set them in a default
			// pose and slam their velocity, angles and origin
			SetAbsOrigin( m_vecRagdollOrigin );

			SetAbsAngles( pPlayer->GetRenderAngles() );

			SetAbsVelocity( m_vecRagdollVelocity );

			int iSeq = LookupSequence( "RagdollSpawn" );	// hax, find a neutral standing pose
			if ( iSeq == -1 )
			{
				Assert( false );	// missing look_idle?
				iSeq = 0;
			}
			
			SetSequence( iSeq );	// look_idle, basic pose
			SetCycle( 0.0 );

			Interp_Reset( varMap );
		}		

		m_nBody = pPlayer->GetBody();
	}
	else
	{
		// overwrite network origin so later interpolation will
		// use this position
		SetNetworkOrigin( m_vecRagdollOrigin );

		SetAbsOrigin( m_vecRagdollOrigin );
		SetAbsVelocity( m_vecRagdollVelocity );

		Interp_Reset( GetVarMapping() );

	}

	SetModelIndex( m_nModelIndex );
	
	// Turn it into a ragdoll.
	if ( cl_ragdoll_physics_enable.GetInt() )
	{
		// Make us a ragdoll..
		m_nRenderFX = kRenderFxRagdoll;

		matrix3x4_t boneDelta0[MAXSTUDIOBONES];
		matrix3x4_t boneDelta1[MAXSTUDIOBONES];
		matrix3x4_t currentBones[MAXSTUDIOBONES];
		const float boneDt = 0.05f;

		if ( pPlayer && pPlayer == C_BasePlayer::GetLocalPlayer() )
		{
			pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}
		else
		{
			GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
		}

		InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
	}
	else
	{
		ClientLeafSystem()->SetRenderGroup( GetRenderHandle(), RENDER_GROUP_TRANSLUCENT_ENTITY );
	}		

	// Fade out the ragdoll in a while
	StartFadeOut( cl_ragdoll_fade_time.GetFloat() );
	SetNextClientThink( gpGlobals->curtime + 5.0f );
}
示例#14
0
void C_EnvelopeFX::RemoveRenderable()
{
	ClientLeafSystem()->RemoveRenderable( m_hRenderHandle );
}
void CClientTools::SetTranslucencyType( IClientRenderable *pRenderable, RenderableTranslucencyType_t nType )
{
	ClientLeafSystem()->SetTranslucencyType( pRenderable->RenderHandle(), nType );
}
void CBulletManager::SimulateBullet(CBullet& oBullet, float dt)
{
	Vector vecOriginal = oBullet.m_vecOrigin;

	Assert(oBullet.m_hShooter.Get());
	if (!oBullet.m_hShooter)
		return;

	bool bHasTraveledBefore = false;
	if (oBullet.m_flDistanceTraveled > 0)
		bHasTraveledBefore = true;

	// initialize these before the penetration loop, we'll need them to make our tracer after
	Vector vecTracerSrc = oBullet.m_vecOrigin;
	trace_t tr; // main enter bullet trace

	float flRange = dt;

	if (flRange < 0)
		flRange = 8000;

	bool bFullPenetrationDistance = false;

	Vector vecEnd = oBullet.m_vecOrigin + oBullet.m_vecDirection * flRange;

	int i;
	for (i = oBullet.m_iPenetrations; i < da_bullet_penetrations.GetInt(); i++)
	{
		CTraceFilterSimpleList tf(COLLISION_GROUP_NONE);
		tf.AddEntityToIgnore(oBullet.m_hShooter);

		for (int j = 0; j < oBullet.m_ahObjectsHit.Count(); j++)
			tf.AddEntityToIgnore(oBullet.m_ahObjectsHit[j]);

		UTIL_TraceLine( oBullet.m_vecOrigin, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &tf, &tr );

		if (da_bullet_debug.GetBool())
		{
#ifdef CLIENT_DLL
			DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 0, 255, 255, true, dt<0?10:0.1);
#else
			DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 255, 255, 0, true, dt<0?10:0.1);
#endif
		}

		Vector vecTraceEnd = tr.endpos;

		bool bBSPModel = tr.DidHitWorld();

		if (tr.allsolid)
		{
			oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length();
			oBullet.m_vecOrigin = vecEnd;
			break; // We're inside something. Do nothing.
		}

		if ( sv_showimpacts.GetBool() && tr.fraction < 1.0f )
		{
#ifdef CLIENT_DLL
			// draw red client impact markers
			debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, sv_showimpacts.GetFloat() );

			if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
			{
				C_BasePlayer *player = ToBasePlayer( tr.m_pEnt );
				player->DrawClientHitboxes( sv_showimpacts.GetFloat(), true );
			}
#else
			// draw blue server impact markers
			NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, sv_showimpacts.GetFloat() );

			if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
			{
				CBasePlayer *player = ToBasePlayer( tr.m_pEnt );
				player->DrawServerHitboxes( sv_showimpacts.GetFloat(), true );
			}
#endif
		}

		Assert(oBullet.m_iBulletType > 0);
		int iDamageType = DMG_BULLET | DMG_NEVERGIB | GetAmmoDef()->DamageType(oBullet.m_iBulletType);

		if (i == 0)
			iDamageType |= DMG_DIRECT;

		if (tr.startsolid)
		{
			trace_t tr2;

			UTIL_TraceLine( tr.endpos - oBullet.m_vecDirection, oBullet.m_vecOrigin, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr2 );

			// let's have a bullet exit effect if we penetrated a solid surface
			if (oBullet.m_bDoEffects && tr2.m_pEnt && tr2.m_pEnt->IsBSPModel())
				UTIL_ImpactTrace( &tr2, iDamageType );

			// ignore the entity we just hit for the next trace to avoid weird impact behaviors
			oBullet.m_ahObjectsHit.AddToTail(tr2.m_pEnt);
		}

		if ( tr.fraction == 1.0f )
		{
			oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length();
			oBullet.m_vecOrigin = vecEnd;
			break; // we didn't hit anything, stop tracing shoot
		}

		weapontype_t eWeaponType = WT_NONE;

		CSDKWeaponInfo *pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(oBullet.m_eWeaponID);
		Assert(pWeaponInfo);
		if (pWeaponInfo)
			eWeaponType = pWeaponInfo->m_eWeaponType;

		float flDamageMultiplier = 1;
		float flMaxRange = 3000;

		// Power formula works like so:
		// pow( x, distance/y )
		// The damage will be at 1 when the distance is 0 units, and at
		// x% when the distance is y units, with a gradual decay approaching zero
		switch (eWeaponType)
		{
		case WT_RIFLE:
			flDamageMultiplier = 0.75f;
			flMaxRange = 3000;
			break;

		case WT_SHOTGUN:
			flDamageMultiplier = 0.40f;
			flMaxRange = 500;
			break;

		case WT_SMG:
			flDamageMultiplier = 0.50f;
			flMaxRange = 1000;
			break;

		case WT_PISTOL:
		default:
			flDamageMultiplier = 0.55f;
			flMaxRange = 1500;
			break;
		}

		flMaxRange *= oBullet.m_hShooter->m_Shared.ModifySkillValue(1, 0.5f, SKILL_MARKSMAN);

		//calculate the damage based on the distance the bullet travelled.
		oBullet.m_flDistanceTraveled += tr.fraction * flRange;

		float flCurrentDistance = oBullet.m_flDistanceTraveled;

		// First 500 units, no decrease in damage.
		if (eWeaponType == WT_SHOTGUN)
			flCurrentDistance -= 350;
		else
			flCurrentDistance -= 500;

		if (flCurrentDistance < 0)
			flCurrentDistance = 0;

		if (flCurrentDistance > flMaxRange)
			flCurrentDistance = flMaxRange;

		float flDistanceMultiplier = pow(flDamageMultiplier, (flCurrentDistance / flMaxRange));

		if( oBullet.m_bDoEffects )
		{
			// See if the bullet ended up underwater + started out of the water
			if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) )
			{
				CBaseEntity* pIgnore;
				if (oBullet.m_ahObjectsHit.Count())
					pIgnore = oBullet.m_ahObjectsHit.Tail();
				else
					pIgnore = oBullet.m_hShooter;

				trace_t waterTrace;
				UTIL_TraceLine( oBullet.m_vecOrigin, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), pIgnore, COLLISION_GROUP_NONE, &waterTrace );

				if( waterTrace.allsolid != 1 )
				{
					CEffectData	data;
					data.m_vOrigin = waterTrace.endpos;
					data.m_vNormal = waterTrace.plane.normal;
					data.m_flScale = random->RandomFloat( 8, 12 );

					if ( waterTrace.contents & CONTENTS_SLIME )
						data.m_fFlags |= FX_WATER_IN_SLIME;

					DispatchEffect( "gunshotsplash", data );
				}
			}
			else
			{
				//Do Regular hit effects

				// Don't decal nodraw surfaces
				if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) )
				{
					CBaseEntity *pEntity = tr.m_pEnt;
					//Tony; only while using teams do we check for friendly fire.
					if ( DAGameRules()->IsTeamplay() && pEntity && pEntity->IsPlayer() && (pEntity->GetBaseAnimating() && !pEntity->GetBaseAnimating()->IsRagdoll()) )
					{
						if ( pEntity->GetTeamNumber() != oBullet.m_hShooter->GetTeamNumber() )
							UTIL_ImpactTrace( &tr, iDamageType );
					}
					//Tony; non player, just go nuts,
					else
						UTIL_ImpactTrace( &tr, iDamageType );
				}
			}
		} // bDoEffects

		// add damage to entity that we hit

#ifdef GAME_DLL
		float flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i+1);	// Each iteration the bullet drops in strength
		if (oBullet.m_hShooter->IsStyleSkillActive(SKILL_MARKSMAN))
			flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i/2+1);	// Each iteration the bullet drops in strength but not nearly as much.

		ClearMultiDamage();

		CTakeDamageInfo info( oBullet.m_hShooter, oBullet.m_hShooter, oBullet.m_hWeapon, flBulletDamage, iDamageType );
		CalculateBulletDamageForce( &info, oBullet.m_iBulletType, oBullet.m_vecDirection, tr.endpos );
		tr.m_pEnt->DispatchTraceAttack( info, oBullet.m_vecDirection, &tr );

		oBullet.m_hShooter->TraceAttackToTriggers( info, tr.startpos, tr.endpos, oBullet.m_vecDirection );

		ApplyMultiDamage();
#else
		flDistanceMultiplier = flDistanceMultiplier; // Silence warning.
#endif

		if (tr.m_pEnt && !FStrEq(tr.m_pEnt->GetClassname(), "worldspawn"))
			oBullet.m_ahObjectsHit.AddToTail(tr.m_pEnt);

		float flPenetrationDistance;
		switch (eWeaponType)
		{
		case WT_RIFLE:
			flPenetrationDistance = 25;
			break;

		case WT_SHOTGUN:
			flPenetrationDistance = 5;
			break;

		case WT_SMG:
			flPenetrationDistance = 15;
			break;

		case WT_PISTOL:
		default:
			flPenetrationDistance = 15;
			break;
		}

		flPenetrationDistance = oBullet.m_hShooter->m_Shared.ModifySkillValue(flPenetrationDistance, 1, SKILL_MARKSMAN);

		Vector vecBackwards = tr.endpos + oBullet.m_vecDirection * flPenetrationDistance;
		if (tr.m_pEnt->IsBSPModel())
			UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr );
		else
			UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_HITBOX, NULL, COLLISION_GROUP_NONE, &tr );

		if (tr.startsolid)
		{
			bFullPenetrationDistance = true;
			break;
		}

		// Set up the next trace. One unit in the direction of fire so that we firmly embed
		// ourselves in whatever solid was hit, to make sure we don't hit it again on next trace.
		if (dt < 0 && bBSPModel)
		{
			UTIL_TraceLine( vecTraceEnd + oBullet.m_vecDirection, vecTraceEnd + oBullet.m_vecDirection * flPenetrationDistance, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr );

			if (tr.startsolid)
				oBullet.m_vecOrigin = tr.startpos + oBullet.m_vecDirection;
			else
				oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection;
		}
		else
			oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection;
	}

	oBullet.m_iPenetrations = i;

	// the bullet's done penetrating, let's spawn our particle system
	if (oBullet.m_bDoEffects && dt < 0)
		oBullet.m_hShooter->MakeTracer( oBullet.m_vecOrigin, tr, TRACER_TYPE_DEFAULT, !bHasTraveledBefore );

#ifdef CLIENT_DLL
	if (oBullet.m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE)
		ClientLeafSystem()->RenderableChanged( oBullet.m_hRenderHandle );
#endif

	if (bFullPenetrationDistance || oBullet.m_iPenetrations >= da_bullet_penetrations.GetInt())
		oBullet.Deactivate();

	if (dt < 0)
		oBullet.Deactivate();

	if (!bHasTraveledBefore && oBullet.m_flCurrAlpha == 0 && oBullet.m_flGoalAlpha == 0)
		oBullet.m_bActive = false;

	if (da_bullet_debug.GetBool())
	{
#ifdef CLIENT_DLL
		DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 0, 0, 255, true, dt<0?10:0.1);
#else
		DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 255, 0, 0, true, dt<0?10:0.1);
#endif
	}
}
//-----------------------------------------------------------------------------
// Purpose: Called when the DLL is first loaded.
// Input  : engineFactory - 
// Output : int
//-----------------------------------------------------------------------------
int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals )
{
	InitCRTMemDebug();
	MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );

	// Hook up global variables
	gpGlobals = pGlobals;

	// We aren't happy unless we get all of our interfaces.
	if(
		!(engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) ||
		!(modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) ||
		!(effects = (IVEfx *)appSystemFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL )) ||
		!(cvar = (ICvar *)appSystemFactory( VENGINE_CVAR_INTERFACE_VERSION, NULL )) ||
		!(enginetrace = (IEngineTrace *)appSystemFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL )) ||
		!(render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) ||
		!(debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL )) ||
		!(materials = (IMaterialSystem *)appSystemFactory( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL )) ||
		!(engineCache = (IVEngineCache*)appSystemFactory(VENGINE_CACHE_INTERFACE_VERSION, NULL )) ||
		!(modelinfo = (IVModelInfo *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) ||
		!(netgraph = (INetGraph *)appSystemFactory(VNETGRAPH_INTERFACE_VERSION, NULL )) ||
		!(enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) ||
		!(networkstringtable = (INetworkStringTableClient *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLECLIENT,NULL)) ||
		!(partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) ||
		!(shadowmgr = (IShadowMgr *)appSystemFactory(ENGINE_SHADOWMGR_INTERFACE_VERSION, NULL)) ||
		!(staticpropmgr = (IStaticPropMgrClient *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_CLIENT, NULL)) ||
		!(enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) ||
		!(filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) ||
		!(random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) ||
		!(gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) ||
		!(gameeventmanager = (IGameEventManager *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER,NULL))
		)
	{
		return false;
	}

	g_pMaterialSystemHardwareConfig = materials->GetHardwareConfig( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, NULL );
	if( !g_pMaterialSystemHardwareConfig )
	{
		return false;
	}

	SetScreenSize();

	// Hook up the gaussian random number generator
	s_GaussianRandomStream.AttachToStream( random );

	// Initialize the console variables.
	ConCommandBaseMgr::OneTimeInit(&g_ConVarAccessor);

	if(!Initializer::InitializeAllObjects())
		return false;

	if(!g_ParticleMgr.Init(8192, materials))
		return false;

	// load used game events  
	gameeventmanager->LoadEventsFromFile("resource/gameevents.res");

	if(!VGui_Startup( appSystemFactory ))
		return false;

	g_pMatSystemSurface = (IMatSystemSurface*)vgui::surface()->QueryInterface( MAT_SYSTEM_SURFACE_INTERFACE_VERSION ); 
	if (!g_pMatSystemSurface)
		return false;

	// Add the client systems.	
	
	// Client Leaf System has to be initialized first, since DetailObjectSystem uses it
	IGameSystem::Add( GameStringSystem() );
	IGameSystem::Add( ClientLeafSystem() );
	IGameSystem::Add( DetailObjectSystem() );
	IGameSystem::Add( ViewportClientSystem() );
	IGameSystem::Add( ClientEffectPrecacheSystem() );
	IGameSystem::Add( g_pClientShadowMgr );
	IGameSystem::Add( ClientThinkList() );
	IGameSystem::Add( ClientSoundscapeSystem() );

#if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST )
	IGameSystem::Add( GetPredictionCopyTester() );
#endif

	modemanager->Init( );

	gHUD.Init();

	g_pClientMode->Init();

	if( !IGameSystem::InitAllSystems() )
		return false;

	g_pClientMode->Enable();

	view->Init();
	vieweffects->Init();

	C_BaseTempEntity::PrecacheTempEnts();

	input->Init_All();

	VGui_CreateGlobalPanels();

	InitSmokeFogOverlay();

	C_TerrainMod_Init();

	// Register user messages..
	CUserMessageRegister::RegisterAll();

	ClientVoiceMgr_Init();

	// Embed voice status icons inside chat element
	{
		CHudChat *chatElement = GET_HUDELEMENT( CHudChat );
		vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL );
		if ( chatElement )
		{
			parent = chatElement->GetVoiceArea()->GetVPanel();
		}
		
		GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent );
	}

	if ( !PhysicsDLLInit( physicsFactory ) )
		return false;

	g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitiySaveRestoreBlockHandler() );
	g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );

	return true;
}