//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $Workfile: $ // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "model_types.h" #include "view_shared.h" #include "iviewrender.h" #include "tempentity.h" #include "dlight.h" #include "tempent.h" #include "c_te_legacytempents.h" #include "clientsideeffects.h" #include "cl_animevent.h" #include "iefx.h" #include "engine/IEngineSound.h" #include "env_wind_shared.h" #include "clienteffectprecachesystem.h" #include "fx_sparks.h" #include "fx.h" #include "movevars_shared.h" #include "engine/ivmodelinfo.h" #include "SoundEmitterSystem/isoundemittersystembase.h" #include "view.h" #include "tier0/vprof.h" #include "particles_localspace.h" #include "physpropclientside.h" #include "tier0/icommandline.h" #include "datacache/imdlcache.h" #include "engine/ivdebugoverlay.h" #include "effect_dispatch_data.h" #include "c_te_effect_dispatch.h" #include "c_props.h" #include "c_basedoor.h" #include "c_baseentity.h" //#include "c_baseanimating.h"//////////OverCharged #include "tracer_filter.h"//////////OverCharged #include "particle_parse.h"//OverCharged #include "c_baseanimating.h" #include "gamestringpool.h" // NOTE: Always include this last! #include "tier0/memdbgon.h" extern ConVar sk_plr_num_shotgun_pellets; ConVar oc_muzzleflash_light_npc("oc_muzzleflash_light_npc", "0", FCVAR_ARCHIVE); ConVar oc_muzzleflash_light_plr("oc_muzzleflash_light_plr", "0", FCVAR_ARCHIVE); ConVar oc_particle_ejectbrass_smoke("oc_particle_ejectbrass_smoke", "0", FCVAR_ARCHIVE); ConVar oc_particle_muzzleflashes("oc_particle_muzzleflashes", "0", FCVAR_ARCHIVE); ConVar oc_particle_tracers("oc_particle_tracers", "0", FCVAR_ARCHIVE); ConVar oc_particle_misc("oc_particle_misc", "0", FCVAR_ARCHIVE); ConVar oc_particle_explosions("oc_particle_explosions", "0", FCVAR_ARCHIVE); ConVar oc_particle_other_weapons("oc_particle_other_weapons", "0", FCVAR_ARCHIVE); ConVar oc_InScope_weapon_muzzleflash_position_x("oc_InScope_weapon_muzzleflash_position_x", "0"); ConVar oc_InScope_weapon_muzzleflash_position_y("oc_InScope_weapon_muzzleflash_position_y", "0"); ConVar oc_InScope_weapon_muzzleflash_position_z("oc_InScope_weapon_muzzleflash_position_z", "0"); ConVar oc_InScope_weapon_tracers_position_x("oc_InScope_weapon_tracers_position_x", "0"); ConVar oc_InScope_weapon_tracers_position_y("oc_InScope_weapon_tracers_position_y", "0"); ConVar oc_InScope_weapon_tracers_position_z("oc_InScope_weapon_tracers_position_z", "0"); ConVar oc_InScope_weapon_muzzleflash_angle_constant("oc_InScope_weapon_muzzleflash_angle_constant", "0"); ConVar oc_InScope_weapon_muzzleflash_angle_z("oc_InScope_weapon_muzzleflash_angle_z", "0"); #define TENT_WIND_ACCEL 50 CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectMuzzleFlash ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash1" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash2" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash3" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash4" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash1_noz" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash2_noz" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash3_noz" ) CLIENTEFFECT_MATERIAL( "effects/muzzleflash4_noz" ) #ifndef CSTRIKE_DLL CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1" ) CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2" ) CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1_noz" ) CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2_noz" ) CLIENTEFFECT_MATERIAL( "effects/strider_muzzle" ) #endif ///////////////////////////////OverCharged///////////////////// CLIENTEFFECT_MATERIAL("effects/muzzleflash1_noz") CLIENTEFFECT_MATERIAL("effects/muzzleflash2_noz") CLIENTEFFECT_MATERIAL("effects/muzzleflash3_noz") CLIENTEFFECT_MATERIAL("effects/muzzleflash4_noz") CLIENTEFFECT_MATERIAL("effects/ar2_muzzle1") CLIENTEFFECT_MATERIAL("effects/combinemuzzle_smoke") CLIENTEFFECT_MATERIAL("effects/strider_muzzle") CLIENTEFFECT_MATERIAL("effects/gunshiptracer") CLIENTEFFECT_MATERIAL("effects/tracer_cap") CLIENTEFFECT_MATERIAL("effects/blueblackflash2") CLIENTEFFECT_MATERIAL("effects/blueblackflash1") CLIENTEFFECT_MATERIAL("effects/muzzleflash1") CLIENTEFFECT_MATERIAL("effects/muzzleflash2") CLIENTEFFECT_MATERIAL("effects/muzzleflash3") CLIENTEFFECT_MATERIAL("effects/muzzleflash4") CLIENTEFFECT_MATERIAL("effects/spark0") CLIENTEFFECT_MATERIAL("effects/combinemuzzle1") CLIENTEFFECT_MATERIAL("effects/combinemuzzle2") ////////////////////////////////////////////////////////////// CLIENTEFFECT_REGISTER_END() ConVar cl_ejectbrass( "cl_ejectbrass", "1" ); ConVar func_break_max_pieces( "func_break_max_pieces", "15", FCVAR_ARCHIVE | FCVAR_REPLICATED ); ConVar cl_fasttempentcollision( "cl_fasttempentcollision", "5" ); #if !defined( HL1_CLIENT_DLL ) // HL1 implements a derivative of CTempEnts // Temp entity interface static CTempEnts g_TempEnts; // Expose to rest of the client .dll ITempEnts *tempents = ( ITempEnts * )&g_TempEnts; #endif C_LocalTempEntity::C_LocalTempEntity() { #ifdef _DEBUG tentOffset.Init(); m_vecTempEntVelocity.Init(); m_vecTempEntAngVelocity.Init(); m_vecNormal.Init(); #endif m_vecTempEntAcceleration.Init(); m_pfnDrawHelper = 0; m_pszImpactEffect = NULL; } #if defined( CSTRIKE_DLL ) || defined (SDK_DLL ) #define TE_RIFLE_SHELL 1024 #define TE_PISTOL_SHELL 2048 #define TE_SHOTGUN_SHELL 4096 #endif //----------------------------------------------------------------------------- // Purpose: Prepare a temp entity for creation // Input : time - // *model - //----------------------------------------------------------------------------- void C_LocalTempEntity::Prepare( const model_t *pmodel, float time ) { Interp_SetupMappings( GetVarMapping() ); index = -1; Clear(); // Use these to set per-frame and termination conditions / actions flags = FTENT_NONE; die = time + 0.75; SetModelPointer( pmodel ); SetRenderMode( kRenderNormal ); m_nRenderFX = kRenderFxNone; m_nBody = 0; m_nSkin = 0; fadeSpeed = 0.5; hitSound = 0; clientIndex = -1; bounceFactor = 1; m_nFlickerFrame = 0; m_bParticleCollision = false; } //----------------------------------------------------------------------------- // Sets the velocity //----------------------------------------------------------------------------- void C_LocalTempEntity::SetVelocity( const Vector &vecVelocity ) { m_vecTempEntVelocity = vecVelocity; } //----------------------------------------------------------------------------- // Sets the velocity //----------------------------------------------------------------------------- void C_LocalTempEntity::SetAcceleration( const Vector &vecVelocity ) { m_vecTempEntAcceleration = vecVelocity; } //----------------------------------------------------------------------------- // Purpose: // Output : int //----------------------------------------------------------------------------- int C_LocalTempEntity::DrawStudioModel( int flags ) { VPROF_BUDGET( "C_LocalTempEntity::DrawStudioModel", VPROF_BUDGETGROUP_MODEL_RENDERING ); int drawn = 0; if ( !GetModel() || modelinfo->GetModelType( GetModel() ) != mod_studio ) return drawn; // Make sure m_pstudiohdr is valid for drawing MDLCACHE_CRITICAL_SECTION(); if ( !GetModelPtr() ) return drawn; if ( m_pfnDrawHelper ) { drawn = ( *m_pfnDrawHelper )( this, flags ); } else { drawn = modelrender->DrawModel( flags, this, MODEL_INSTANCE_INVALID, index, GetModel(), GetAbsOrigin(), GetAbsAngles(), m_nSkin, m_nBody, m_nHitboxSet ); } return drawn; } //----------------------------------------------------------------------------- // Purpose: // Input : flags - //----------------------------------------------------------------------------- int C_LocalTempEntity::DrawModel( int flags ) { int drawn = 0; if ( !GetModel() ) { return drawn; } if ( GetRenderMode() == kRenderNone ) return drawn; if ( this->flags & FTENT_BEOCCLUDED ) { // Check normal Vector vecDelta = (GetAbsOrigin() - MainViewOrigin()); VectorNormalize( vecDelta ); float flDot = DotProduct( m_vecNormal, vecDelta ); if ( flDot > 0 ) { float flAlpha = RemapVal( MIN(flDot,0.3), 0, 0.3, 0, 1 ); flAlpha = MAX( 1.0, tempent_renderamt - (tempent_renderamt * flAlpha) ); SetRenderColorA( flAlpha ); } } switch ( modelinfo->GetModelType( GetModel() ) ) { case mod_sprite: drawn = DrawSprite( this, GetModel(), GetAbsOrigin(), GetAbsAngles(), m_flFrame, // sprite frame to render m_nBody > 0 ? cl_entitylist->GetBaseEntity( m_nBody ) : NULL, // attach to m_nSkin, // attachment point GetRenderMode(), // rendermode m_nRenderFX, // renderfx m_clrRender->a, // alpha m_clrRender->r, m_clrRender->g, m_clrRender->b, m_flSpriteScale // sprite scale ); break; case mod_studio: drawn = DrawStudioModel( flags ); break; default: break; } return drawn; } //----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool C_LocalTempEntity::IsActive( void ) { bool active = true; float life = die - gpGlobals->curtime; if ( life < 0 ) { if ( flags & FTENT_FADEOUT ) { int alpha; if (GetRenderMode() == kRenderNormal) { SetRenderMode( kRenderTransTexture ); } alpha = tempent_renderamt * ( 1 + life * fadeSpeed ); if ( alpha <= 0 ) { active = false; alpha = 0; } SetRenderColorA( alpha ); } else { active = false; } } // Never die tempents only die when their die is cleared if ( flags & FTENT_NEVERDIE ) { active = (die != 0); } return active; ///////////////////////////////////////////////////////////////////////////////////////OOOOOOLD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* bool active = true; float life = die - gpGlobals->curtime; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer) { //if ( (life >= 0.65 ) && ( flags & FTENT_SMOKE ) && ( sv_ejectbrass_smoke.GetBool() == true ) && ( cl_ejectbrass.GetBool() == true ) ) if ( (life >= 0.65f ) && ( flags & ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE | FTENT_SMOKE) ) && ( sv_ejectbrass_smoke.GetBool() == true ) && ( cl_ejectbrass.GetBool() == true ) ) { CSmartPtr pSimple = CSimpleEmitter::Create( "EjectBrass" ); SimpleParticle *sParticle; pSimple->SetDrawBeforeViewModel( true ); sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[1], GetLocalOrigin() );//pSimple->GetPMaterial( "effects/spark2" ),//g_Mat_DustPuff[RandomInt(0,1)] // if ( sParticle == NULL ) // return; sParticle->m_flLifetime = 0.01f; sParticle->m_flDieTime = 0.33f; // sParticle->m_flDieTime = D; sParticle->m_vecVelocity.Init(); sParticle->m_vecVelocity = 2; //* random->RandomFloat( 8.0f, 64.0f ); // sParticle->m_vecVelocity[2] += random->RandomFloat( 4.0f, 16.0f ); int color = 255;//random->RandomInt( 255, 300 ); sParticle->m_uchColor[0] = color; sParticle->m_uchColor[1] = color; sParticle->m_uchColor[2] = color; sParticle->m_uchStartAlpha = random->RandomInt( 1500, 1800 ); sParticle->m_uchEndAlpha = 0; sParticle->m_uchStartSize = random->RandomInt( 1.0f, 1.1f ); sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.5f; sParticle->m_flRoll = random->RandomInt( 0, 360 ); sParticle->m_flRollDelta = random->RandomFloat( -0.5f, 0.5f ); // DispatchParticleEffect( "muzzle_smoke_shotgun_flash", GetLocalOrigin(), QAngle(0,0,0) ); // i++; }*/ } bool C_LocalTempEntity::Frame( float frametime, int framenumber ) { float fastFreq = gpGlobals->curtime * 5.5; float gravity = -frametime * GetCurrentGravity(); float gravitySlow = gravity * 0.5; float traceFraction = 1; Assert( !GetMoveParent() ); m_vecPrevLocalOrigin = GetLocalOrigin(); m_vecTempEntVelocity = m_vecTempEntVelocity + ( m_vecTempEntAcceleration * frametime ); if ( flags & FTENT_PLYRATTACHMENT ) { if ( IClientEntity *pClient = cl_entitylist->GetClientEntity( clientIndex ) ) { SetLocalOrigin( pClient->GetAbsOrigin() + tentOffset ); } } else if ( flags & FTENT_SINEWAVE ) { x += m_vecTempEntVelocity[0] * frametime; y += m_vecTempEntVelocity[1] * frametime; SetLocalOrigin( Vector( x + sin( m_vecTempEntVelocity[2] + gpGlobals->curtime /* * anim.prevframe */ ) * (10*m_flSpriteScale), y + sin( m_vecTempEntVelocity[2] + fastFreq + 0.7 ) * (8*m_flSpriteScale), GetLocalOriginDim( Z_INDEX ) + m_vecTempEntVelocity[2] * frametime ) ); } else if ( flags & FTENT_SPIRAL ) { float s, c; SinCos( m_vecTempEntVelocity[2] + fastFreq, &s, &c ); SetLocalOrigin( GetLocalOrigin() + Vector( m_vecTempEntVelocity[0] * frametime + 8 * sin( gpGlobals->curtime * 20 ), m_vecTempEntVelocity[1] * frametime + 4 * sin( gpGlobals->curtime * 30 ), m_vecTempEntVelocity[2] * frametime ) ); } else { SetLocalOrigin( GetLocalOrigin() + m_vecTempEntVelocity * frametime ); } if ( flags & FTENT_SPRANIMATE ) { m_flFrame += frametime * m_flFrameRate; if ( m_flFrame >= m_flFrameMax ) { m_flFrame = m_flFrame - (int)(m_flFrame); if ( !(flags & FTENT_SPRANIMATELOOP) ) { // this animating sprite isn't set to loop, so destroy it. die = 0.0f; return false; } } } else if ( flags & FTENT_SPRCYCLE ) { m_flFrame += frametime * 10; if ( m_flFrame >= m_flFrameMax ) { m_flFrame = m_flFrame - (int)(m_flFrame); } } if ( flags & FTENT_SMOKEGROWANDFADE ) { m_flSpriteScale += frametime * 0.5f; //m_clrRender.a -= frametime * 1500; } if ( flags & FTENT_ROTATE ) { SetLocalAngles( GetLocalAngles() + m_vecTempEntAngVelocity * frametime ); } else if ( flags & FTENT_ALIGNTOMOTION ) { if ( m_vecTempEntVelocity.Length() > 0.0f ) { QAngle angles; VectorAngles( m_vecTempEntVelocity, angles ); SetAbsAngles( angles ); } } if ( flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD | FTENT_COLLIDEPROPS ) ) { Vector traceNormal; traceNormal.Init(); bool bShouldCollide = true; trace_t trace; if ( flags & (FTENT_COLLIDEALL | FTENT_COLLIDEPROPS) ) { Vector vPrevOrigin = m_vecPrevLocalOrigin; if ( cl_fasttempentcollision.GetInt() > 0 && flags & FTENT_USEFASTCOLLISIONS ) { if ( m_iLastCollisionFrame + cl_fasttempentcollision.GetInt() > gpGlobals->framecount ) { bShouldCollide = false; } else { if ( m_vLastCollisionOrigin != vec3_origin ) { vPrevOrigin = m_vLastCollisionOrigin; } m_iLastCollisionFrame = gpGlobals->framecount; bShouldCollide = true; } } if ( bShouldCollide == true ) { // If the FTENT_COLLISIONGROUP flag is set, use the entity's collision group int collisionGroup = COLLISION_GROUP_NONE; if ( flags & FTENT_COLLISIONGROUP ) { collisionGroup = GetCollisionGroup(); } UTIL_TraceLine( vPrevOrigin, GetLocalOrigin(), MASK_SOLID, GetOwnerEntity(), collisionGroup, &trace ); if ( (flags & FTENT_COLLIDEPROPS) && trace.m_pEnt ) { bool bIsDynamicProp = ( NULL != dynamic_cast( trace.m_pEnt ) ); bool bIsDoor = ( NULL != dynamic_cast( trace.m_pEnt ) ); if ( !bIsDynamicProp && !bIsDoor && !trace.m_pEnt->IsWorld() ) // Die on props, doors, and the world. return true; } // Make sure it didn't bump into itself... (?!?) if ( (trace.fraction != 1) && ( (trace.DidHitWorld()) || (trace.m_pEnt != ClientEntityList().GetEnt(clientIndex)) ) ) { traceFraction = trace.fraction; VectorCopy( trace.plane.normal, traceNormal ); } m_vLastCollisionOrigin = trace.endpos; } } else if ( flags & FTENT_COLLIDEWORLD ) { CTraceFilterWorldOnly traceFilter; UTIL_TraceLine( m_vecPrevLocalOrigin, GetLocalOrigin(), MASK_SOLID, &traceFilter, &trace ); if ( trace.fraction != 1 ) { traceFraction = trace.fraction; VectorCopy( trace.plane.normal, traceNormal ); } } if ( traceFraction != 1 ) // Decent collision now, and damping works { float proj, damp; SetLocalOrigin( trace.endpos ); // Damp velocity damp = bounceFactor; if ( flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) ) { damp *= 0.5; if ( traceNormal[2] > 0.9 ) // Hit floor? { if ( m_vecTempEntVelocity[2] <= 0 && m_vecTempEntVelocity[2] >= gravity*3 ) { damp = 0; // Stop flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL); SetLocalAnglesDim( X_INDEX, 0 ); SetLocalAnglesDim( Z_INDEX, 0 ); } } } if ( flags & (FTENT_CHANGERENDERONCOLLIDE) ) { m_RenderGroup = RENDER_GROUP_OTHER; flags &= ~FTENT_CHANGERENDERONCOLLIDE; } if (hitSound) { tempents->PlaySound(this, damp); } if ( m_pszImpactEffect ) { CEffectData data; //data.m_vOrigin = newOrigin; data.m_vOrigin = trace.endpos; data.m_vStart = trace.startpos; data.m_nSurfaceProp = trace.surface.surfaceProps; data.m_nHitBox = trace.hitbox; data.m_nDamageType = TEAM_UNASSIGNED; IClientNetworkable *pClient = cl_entitylist->GetClientEntity( clientIndex ); if ( pClient ) { C_BasePlayer *pPlayer = dynamic_cast(pClient); if( pPlayer ) { data.m_nDamageType = pPlayer->GetTeamNumber(); } } if ( trace.m_pEnt ) { data.m_hEntity = ClientEntityList().EntIndexToHandle( trace.m_pEnt->entindex() ); } DispatchEffect( m_pszImpactEffect, data ); } // Check for a collision and stop the particle system. if ( flags & FTENT_CLIENTSIDEPARTICLES ) { // Stop the emission of particles on collision - removed from the ClientEntityList on removal from the tempent pool. ParticleProp()->StopEmission(); m_bParticleCollision = true; } if (flags & FTENT_COLLIDEKILL) { // die on impact flags &= ~FTENT_FADEOUT; die = gpGlobals->curtime; } else if ( flags & FTENT_ATTACHTOTARGET) { // If we've hit the world, just stop moving if ( trace.DidHitWorld() && !( trace.surface.flags & SURF_SKY ) ) { m_vecTempEntVelocity = vec3_origin; m_vecTempEntAcceleration = vec3_origin; // Remove movement flags so we don't keep tracing flags &= ~(FTENT_COLLIDEALL | FTENT_COLLIDEWORLD); } else { // Couldn't attach to this entity. Die. flags &= ~FTENT_FADEOUT; die = gpGlobals->curtime; } } else { // Reflect velocity if ( damp != 0 ) { proj = ((Vector)m_vecTempEntVelocity).Dot(traceNormal); VectorMA( m_vecTempEntVelocity, -proj*2, traceNormal, m_vecTempEntVelocity ); // Reflect rotation (fake) SetLocalAnglesDim( Y_INDEX, -GetLocalAnglesDim( Y_INDEX ) ); } if ( damp != 1 ) { VectorScale( m_vecTempEntVelocity, damp, m_vecTempEntVelocity ); SetLocalAngles( GetLocalAngles() * 0.9 ); } } } } if ( (flags & FTENT_FLICKER) && framenumber == m_nFlickerFrame ) { dlight_t *dl = effects->CL_AllocDlight (LIGHT_INDEX_TE_DYNAMIC); VectorCopy (GetLocalOrigin(), dl->origin); dl->radius = 60; dl->color.r = 255; dl->color.g = 120; dl->color.b = 0; dl->die = gpGlobals->curtime + 0.01; } if ( flags & FTENT_SMOKETRAIL ) { Assert( !"FIXME: Rework smoketrail to be client side\n" ); } // add gravity if we didn't collide in this frame if ( traceFraction == 1 ) { if ( flags & FTENT_GRAVITY ) m_vecTempEntVelocity[2] += gravity; else if ( flags & FTENT_SLOWGRAVITY ) m_vecTempEntVelocity[2] += gravitySlow; } if ( flags & FTENT_WINDBLOWN ) { Vector vecWind; GetWindspeedAtTime( gpGlobals->curtime, vecWind ); for ( int i = 0 ; i < 2 ; i++ ) { if ( m_vecTempEntVelocity[i] < vecWind[i] ) { m_vecTempEntVelocity[i] += ( frametime * TENT_WIND_ACCEL ); // clamp if ( m_vecTempEntVelocity[i] > vecWind[i] ) m_vecTempEntVelocity[i] = vecWind[i]; } else if (m_vecTempEntVelocity[i] > vecWind[i] ) { m_vecTempEntVelocity[i] -= ( frametime * TENT_WIND_ACCEL ); // clamp. if ( m_vecTempEntVelocity[i] < vecWind[i] ) m_vecTempEntVelocity[i] = vecWind[i]; } } } return true; } //----------------------------------------------------------------------------- // Purpose: Attach a particle effect to a temp entity. //----------------------------------------------------------------------------- CNewParticleEffect* C_LocalTempEntity::AddParticleEffect( const char *pszParticleEffect ) { // Do we have a valid particle effect. if ( !pszParticleEffect || ( pszParticleEffect[0] == '\0' ) ) return NULL; // Check to see that we don't already have a particle effect. if ( ( flags & FTENT_CLIENTSIDEPARTICLES ) != 0 ) return NULL; // Add the entity to the ClientEntityList and create the particle system. ClientEntityList().AddNonNetworkableEntity( this ); CNewParticleEffect* pEffect = ParticleProp()->Create( pszParticleEffect, PATTACH_ABSORIGIN_FOLLOW ); // Set the particle flag on the temp entity and save the name of the particle effect. flags |= FTENT_CLIENTSIDEPARTICLES; SetParticleEffect( pszParticleEffect ); return pEffect; } //----------------------------------------------------------------------------- // Purpose: This helper keeps track of batches of "breakmodels" so that they can all share the lighting origin // of the first of the group (because the server sends down 15 chunks at a time, and rebuilding 15 light cache // entries for a map with a lot of worldlights is really slow). //----------------------------------------------------------------------------- class CBreakableHelper { public: void Insert( C_LocalTempEntity *entity, bool isSlave ); void Remove( C_LocalTempEntity *entity ); void Clear(); const Vector *GetLightingOrigin( C_LocalTempEntity *entity ); private: // A context is the first master until the next one, which starts a new context struct BreakableList_t { unsigned int context; C_LocalTempEntity *entity; }; CUtlLinkedList< BreakableList_t, unsigned short > m_Breakables; unsigned int m_nCurrentContext; }; //----------------------------------------------------------------------------- // Purpose: Adds brekable to list, starts new context if needed // Input : *entity - // isSlave - //----------------------------------------------------------------------------- void CBreakableHelper::Insert( C_LocalTempEntity *entity, bool isSlave ) { // A master signifies the start of a new run of broken objects if ( !isSlave ) { ++m_nCurrentContext; } BreakableList_t entry; entry.context = m_nCurrentContext; entry.entity = entity; m_Breakables.AddToTail( entry ); } //----------------------------------------------------------------------------- // Purpose: Removes all instances of entity in the list // Input : *entity - //----------------------------------------------------------------------------- void CBreakableHelper::Remove( C_LocalTempEntity *entity ) { for ( unsigned short i = m_Breakables.Head(); i != m_Breakables.InvalidIndex() ; ) { unsigned short n = m_Breakables.Next( i ); if ( m_Breakables[ i ].entity == entity ) { m_Breakables.Remove( i ); } i = n; } } //----------------------------------------------------------------------------- // Purpose: For a given breakable, find the "first" or head object and use it's current // origin as the lighting origin for the entire group of objects // Input : *entity - // Output : const Vector //----------------------------------------------------------------------------- const Vector *CBreakableHelper::GetLightingOrigin( C_LocalTempEntity *entity ) { unsigned int nCurContext = 0; C_LocalTempEntity *head = NULL; FOR_EACH_LL( m_Breakables, i ) { BreakableList_t& e = m_Breakables[ i ]; if ( e.context != nCurContext ) { nCurContext = e.context; head = e.entity; } if ( e.entity == entity ) { Assert( head ); return head ? &head->GetAbsOrigin() : NULL; } } return NULL; } //----------------------------------------------------------------------------- // Purpose: Wipe breakable helper list // Input : - //----------------------------------------------------------------------------- void CBreakableHelper::Clear() { m_Breakables.RemoveAll(); m_nCurrentContext = 0; } static CBreakableHelper g_BreakableHelper; //----------------------------------------------------------------------------- // Purpose: See if it's in the breakable helper list and, if so, remove // Input : - //----------------------------------------------------------------------------- void C_LocalTempEntity::OnRemoveTempEntity() { g_BreakableHelper.Remove( this ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CTempEnts::CTempEnts( void ) : m_TempEntsPool( ( MAX_TEMP_ENTITIES / 20 ), CUtlMemoryPool::GROW_SLOW ) { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CTempEnts::~CTempEnts( void ) { m_TempEntsPool.Clear(); m_TempEnts.RemoveAll(); } //----------------------------------------------------------------------------- // Purpose: Create a fizz effect // Input : *pent - // modelIndex - // density - //----------------------------------------------------------------------------- void CTempEnts::FizzEffect( C_BaseEntity *pent, int modelIndex, int density, int current ) { C_LocalTempEntity *pTemp; const model_t *model; int i, width, depth, count, frameCount; float maxHeight, speed, xspeed, yspeed; Vector origin; Vector mins, maxs; if ( !pent->GetModel() || !modelIndex ) return; model = modelinfo->GetModel( modelIndex ); if ( !model ) return; count = density + 1; density = count * 3 + 6; modelinfo->GetModelBounds( pent->GetModel(), mins, maxs ); maxHeight = maxs[2] - mins[2]; width = maxs[0] - mins[0]; depth = maxs[1] - mins[1]; speed = current; SinCos( pent->GetLocalAngles()[1]*M_PI/180, &yspeed, &xspeed ); xspeed *= speed; yspeed *= speed; frameCount = modelinfo->GetModelFrameCount( model ); for (i=0 ; iRandomInt(0,width-1); origin[1] = mins[1] + random->RandomInt(0,depth-1); origin[2] = mins[2]; pTemp = TempEntAlloc( origin, model ); if (!pTemp) return; pTemp->flags |= FTENT_SINEWAVE; pTemp->x = origin[0]; pTemp->y = origin[1]; float zspeed = random->RandomInt(80,140); pTemp->SetVelocity( Vector(xspeed, yspeed, zspeed) ); pTemp->die = gpGlobals->curtime + (maxHeight / zspeed) - 0.1; pTemp->m_flFrame = random->RandomInt(0,frameCount-1); // Set sprite scale pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(2,5); pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->SetRenderColorA( 255 ); } } //----------------------------------------------------------------------------- // Purpose: Create bubbles // Input : *mins - // *maxs - // height - // modelIndex - // count - // speed - //----------------------------------------------------------------------------- void CTempEnts::Bubbles( const Vector &mins, const Vector &maxs, float height, int modelIndex, int count, float speed ) { C_LocalTempEntity *pTemp; const model_t *model; int i, frameCount; float sine, cosine; Vector origin; if ( !modelIndex ) return; model = modelinfo->GetModel( modelIndex ); if ( !model ) return; frameCount = modelinfo->GetModelFrameCount( model ); for (i=0 ; iRandomInt( mins[0], maxs[0] ); origin[1] = random->RandomInt( mins[1], maxs[1] ); origin[2] = random->RandomInt( mins[2], maxs[2] ); pTemp = TempEntAlloc( origin, model ); if (!pTemp) return; pTemp->flags |= FTENT_SINEWAVE; pTemp->x = origin[0]; pTemp->y = origin[1]; SinCos( random->RandomInt( -3, 3 ), &sine, &cosine ); float zspeed = random->RandomInt(80,140); pTemp->SetVelocity( Vector(speed * cosine, speed * sine, zspeed) ); pTemp->die = gpGlobals->curtime + ((height - (origin[2] - mins[2])) / zspeed) - 0.1; pTemp->m_flFrame = random->RandomInt( 0, frameCount-1 ); // Set sprite scale pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(4,16); pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->SetRenderColor( 255, 255, 255, 192 ); } } //----------------------------------------------------------------------------- // Purpose: Create bubble trail // Input : *start - // *end - // height - // modelIndex - // count - // speed - //----------------------------------------------------------------------------- void CTempEnts::BubbleTrail( const Vector &start, const Vector &end, float flWaterZ, int modelIndex, int count, float speed ) { C_LocalTempEntity *pTemp; const model_t *model; int i, frameCount; float dist, angle; Vector origin; if ( !modelIndex ) return; model = modelinfo->GetModel( modelIndex ); if ( !model ) return; frameCount = modelinfo->GetModelFrameCount( model ); for (i=0 ; iRandomFloat( 0, 1.0 ); VectorLerp( start, end, dist, origin ); pTemp = TempEntAlloc( origin, model ); if (!pTemp) return; pTemp->flags |= FTENT_SINEWAVE; pTemp->x = origin[0]; pTemp->y = origin[1]; angle = random->RandomInt( -3, 3 ); float zspeed = random->RandomInt(80,140); pTemp->SetVelocity( Vector(speed * cos(angle), speed * sin(angle), zspeed) ); pTemp->die = gpGlobals->curtime + ((flWaterZ - origin[2]) / zspeed) - 0.1; pTemp->m_flFrame = random->RandomInt(0,frameCount-1); // Set sprite scale pTemp->m_flSpriteScale = 1.0 / random->RandomFloat(4,8); pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->SetRenderColor( 255, 255, 255, 192 ); } } #define SHARD_VOLUME 12.0 // on shard ever n^3 units //----------------------------------------------------------------------------- // Purpose: Only used by BreakModel temp ents for now. Allows them to share a single // lighting origin amongst a group of objects. If the master object goes away, the next object // in the group becomes the new lighting origin, etc. // Input : *entity - // flags - // Output : int //----------------------------------------------------------------------------- int BreakModelDrawHelper( C_LocalTempEntity *entity, int flags ) { ModelRenderInfo_t sInfo; sInfo.flags = flags; sInfo.pRenderable = entity; sInfo.instance = MODEL_INSTANCE_INVALID; sInfo.entity_index = entity->index; sInfo.pModel = entity->GetModel(); sInfo.origin = entity->GetRenderOrigin(); sInfo.angles = entity->GetRenderAngles(); sInfo.skin = entity->m_nSkin; sInfo.body = entity->m_nBody; sInfo.hitboxset = entity->m_nHitboxSet; // This is the main change, look up a lighting origin from the helper singleton const Vector *pLightingOrigin = g_BreakableHelper.GetLightingOrigin( entity ); if ( pLightingOrigin ) { sInfo.pLightingOrigin = pLightingOrigin; } int drawn = modelrender->DrawModelEx( sInfo ); return drawn; } //----------------------------------------------------------------------------- // Purpose: Create model shattering shards // Input : *pos - // *size - // *dir - // random - // life - // count - // modelIndex - // flags - //----------------------------------------------------------------------------- void CTempEnts::BreakModel( const Vector &pos, const QAngle &angles, const Vector &size, const Vector &dir, float randRange, float life, int count, int modelIndex, char flags) { int i, frameCount; C_LocalTempEntity *pTemp; const model_t *pModel; if (!modelIndex) return; pModel = modelinfo->GetModel( modelIndex ); if ( !pModel ) return; // See g_BreakableHelper above for notes... bool isSlave = ( flags & BREAK_SLAVE ) ? true : false; frameCount = modelinfo->GetModelFrameCount( pModel ); if (count == 0) { // assume surface (not volume) count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0])/(3 * SHARD_VOLUME * SHARD_VOLUME); } if ( count > func_break_max_pieces.GetInt() ) { count = func_break_max_pieces.GetInt(); } matrix3x4_t transform; AngleMatrix( angles, pos, transform ); for ( i = 0; i < count; i++ ) { Vector vecLocalSpot, vecSpot; // fill up the box with stuff vecLocalSpot[0] = random->RandomFloat(-0.5,0.5) * size[0]; vecLocalSpot[1] = random->RandomFloat(-0.5,0.5) * size[1]; vecLocalSpot[2] = random->RandomFloat(-0.5,0.5) * size[2]; VectorTransform( vecLocalSpot, transform, vecSpot ); pTemp = TempEntAlloc(vecSpot, pModel); if (!pTemp) return; // keep track of break_type, so we know how to play sound on collision pTemp->hitSound = flags; if ( modelinfo->GetModelType( pModel ) == mod_sprite ) { pTemp->m_flFrame = random->RandomInt(0,frameCount-1); } else if ( modelinfo->GetModelType( pModel ) == mod_studio ) { pTemp->m_nBody = random->RandomInt(0,frameCount-1); } pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_SLOWGRAVITY; if ( random->RandomInt(0,255) < 200 ) { pTemp->flags |= FTENT_ROTATE; pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-256,255); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-256,255); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-256,255); } if ( (random->RandomInt(0,255) < 100 ) && (flags & BREAK_SMOKE) ) { pTemp->flags |= FTENT_SMOKETRAIL; } if ((flags & BREAK_GLASS) || (flags & BREAK_TRANS)) { pTemp->SetRenderMode( kRenderTransTexture ); pTemp->SetRenderColorA( 128 ); pTemp->tempent_renderamt = 128; pTemp->bounceFactor = 0.3f; } else { pTemp->SetRenderMode( kRenderNormal ); pTemp->tempent_renderamt = 255; // Set this for fadeout } pTemp->SetVelocity( Vector( dir[0] + random->RandomFloat(-randRange,randRange), dir[1] + random->RandomFloat(-randRange,randRange), dir[2] + random->RandomFloat( 0,randRange) ) ); pTemp->die = gpGlobals->curtime + life + random->RandomFloat(0,1); // Add an extra 0-1 secs of life // We use a special rendering function because these objects will want to share their lighting // origin with the first/master object. Prevents a huge spike in Light Cache building in maps // with many worldlights. pTemp->SetDrawHelper( BreakModelDrawHelper ); g_BreakableHelper.Insert( pTemp, isSlave ); } } void CTempEnts::PhysicsProp( int modelindex, int skin, const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects ) { C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew(); if ( !pEntity ) return; const model_t *model = modelinfo->GetModel( modelindex ); if ( !model ) { DevMsg("CTempEnts::PhysicsProp: model index %i not found\n", modelindex ); return; } pEntity->SetModelName( modelinfo->GetModelName(model) ); pEntity->m_nSkin = skin; pEntity->SetAbsOrigin( pos ); pEntity->SetAbsAngles( angles ); pEntity->SetPhysicsMode( PHYSICS_MULTIPLAYER_CLIENTSIDE ); pEntity->SetEffects( effects ); if ( !pEntity->Initialize() ) { pEntity->Release(); return; } IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if( pPhysicsObject ) { pPhysicsObject->AddVelocity( &vel, NULL ); } else { // failed to create a physics object pEntity->Release(); return; } if ( flags & 1 ) { pEntity->SetHealth( 0 ); pEntity->Break(); } } //----------------------------------------------------------------------------- // Purpose: Create a clientside projectile // Input : vecOrigin - // vecVelocity - // modelindex - // lifetime - // *pOwner - //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::ClientProjectile( const Vector& vecOrigin, const Vector& vecVelocity, const Vector& vecAcceleration, int modelIndex, int lifetime, CBaseEntity *pOwner, const char *pszImpactEffect, const char *pszParticleEffect ) { C_LocalTempEntity *pTemp; const model_t *model; if ( !modelIndex ) return NULL; model = modelinfo->GetModel( modelIndex ); if ( !model ) { Warning("ClientProjectile: No model %d!\n", modelIndex); return NULL; } pTemp = TempEntAlloc( vecOrigin, model ); if (!pTemp) return NULL; pTemp->SetVelocity( vecVelocity ); pTemp->SetAcceleration( vecAcceleration ); QAngle angles; VectorAngles( vecVelocity, angles ); pTemp->SetAbsAngles( angles ); pTemp->SetAbsOrigin( vecOrigin ); pTemp->die = gpGlobals->curtime + lifetime; pTemp->flags = FTENT_COLLIDEALL | FTENT_ATTACHTOTARGET | FTENT_ALIGNTOMOTION; pTemp->clientIndex = ( pOwner != NULL ) ? pOwner->entindex() : 0; pTemp->SetOwnerEntity( pOwner ); pTemp->SetImpactEffect( pszImpactEffect ); if ( pszParticleEffect ) { // Add the entity to the ClientEntityList and create the particle system. ClientEntityList().AddNonNetworkableEntity( pTemp ); pTemp->ParticleProp()->Create( pszParticleEffect, PATTACH_ABSORIGIN_FOLLOW ); // Set the particle flag on the temp entity and save the name of the particle effect. pTemp->flags |= FTENT_CLIENTSIDEPARTICLES; pTemp->SetParticleEffect( pszParticleEffect ); } return pTemp; } //----------------------------------------------------------------------------- // Purpose: Create sprite TE // Input : *pos - // *dir - // scale - // modelIndex - // rendermode - // renderfx - // a - // life - // flags - // Output : C_LocalTempEntity //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::TempSprite( const Vector &pos, const Vector &dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags, const Vector &normal ) { C_LocalTempEntity *pTemp; const model_t *model; int frameCount; if ( !modelIndex ) return NULL; model = modelinfo->GetModel( modelIndex ); if ( !model ) { Warning("No model %d!\n", modelIndex); return NULL; } frameCount = modelinfo->GetModelFrameCount( model ); pTemp = TempEntAlloc( pos, model ); if (!pTemp) return NULL; pTemp->m_flFrameMax = frameCount - 1; pTemp->m_flFrameRate = 10; pTemp->SetRenderMode( (RenderMode_t)rendermode ); pTemp->m_nRenderFX = renderfx; pTemp->m_flSpriteScale = scale; pTemp->tempent_renderamt = a * 255; pTemp->m_vecNormal = normal; pTemp->SetRenderColor( 255, 255, 255, a * 255 ); pTemp->flags |= flags; pTemp->SetVelocity( dir ); pTemp->SetLocalOrigin( pos ); if ( life ) pTemp->die = gpGlobals->curtime + life; else pTemp->die = gpGlobals->curtime + (frameCount * 0.1) + 1; pTemp->m_flFrame = 0; return pTemp; } //----------------------------------------------------------------------------- // Purpose: Spray sprite // Input : *pos - // *dir - // modelIndex - // count - // speed - // iRand - //----------------------------------------------------------------------------- void CTempEnts::Sprite_Spray( const Vector &pos, const Vector &dir, int modelIndex, int count, int speed, int iRand ) { C_LocalTempEntity *pTemp; const model_t *pModel; float noise; float znoise; int frameCount; int i; noise = (float)iRand / 100; // more vertical displacement znoise = noise * 1.5; if ( znoise > 1 ) { znoise = 1; } pModel = modelinfo->GetModel( modelIndex ); if ( !pModel ) { Warning("No model %d!\n", modelIndex); return; } frameCount = modelinfo->GetModelFrameCount( pModel ) - 1; for ( i = 0; i < count; i++ ) { pTemp = TempEntAlloc( pos, pModel ); if (!pTemp) return; pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->SetRenderColor( 255, 255, 255, 255 ); pTemp->tempent_renderamt = 255; pTemp->m_nRenderFX = kRenderFxNoDissipation; //pTemp->scale = random->RandomFloat( 0.1, 0.25 ); pTemp->m_flSpriteScale = 0.5; pTemp->flags |= FTENT_FADEOUT | FTENT_SLOWGRAVITY; pTemp->fadeSpeed = 2.0; // make the spittle fly the direction indicated, but mix in some noise. Vector velocity; velocity.x = dir[ 0 ] + random->RandomFloat ( -noise, noise ); velocity.y = dir[ 1 ] + random->RandomFloat ( -noise, noise ); velocity.z = dir[ 2 ] + random->RandomFloat ( 0, znoise ); velocity *= random->RandomFloat( (speed * 0.8), (speed * 1.2) ); pTemp->SetVelocity( velocity ); pTemp->SetLocalOrigin( pos ); pTemp->die = gpGlobals->curtime + 0.35; pTemp->m_flFrame = random->RandomInt( 0, frameCount ); } } void CTempEnts::Sprite_Trail( const Vector &vecStart, const Vector &vecEnd, int modelIndex, int nCount, float flLife, float flSize, float flAmplitude, int nRenderamt, float flSpeed ) { C_LocalTempEntity *pTemp; const model_t *pModel; int flFrameCount; pModel = modelinfo->GetModel( modelIndex ); if ( !pModel ) { Warning("No model %d!\n", modelIndex); return; } flFrameCount = modelinfo->GetModelFrameCount( pModel ); Vector vecDelta; VectorSubtract( vecEnd, vecStart, vecDelta ); Vector vecDir; VectorCopy( vecDelta, vecDir ); VectorNormalize( vecDir ); flAmplitude /= 256.0; for ( int i = 0 ; i < nCount; i++ ) { Vector vecPos; // Be careful of divide by 0 when using 'count' here... if ( i == 0 ) { VectorMA( vecStart, 0, vecDelta, vecPos ); } else { VectorMA( vecStart, i / (nCount - 1.0), vecDelta, vecPos ); } pTemp = TempEntAlloc( vecPos, pModel ); if (!pTemp) return; pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SPRCYCLE | FTENT_FADEOUT | FTENT_SLOWGRAVITY; Vector vecVel = vecDir * flSpeed; vecVel.x += random->RandomInt( -127,128 ) * flAmplitude; vecVel.y += random->RandomInt( -127,128 ) * flAmplitude; vecVel.z += random->RandomInt( -127,128 ) * flAmplitude; pTemp->SetVelocity( vecVel ); pTemp->SetLocalOrigin( vecPos ); pTemp->m_flSpriteScale = flSize; pTemp->SetRenderMode( kRenderGlow ); pTemp->m_nRenderFX = kRenderFxNoDissipation; pTemp->tempent_renderamt = nRenderamt; pTemp->SetRenderColor( 255, 255, 255 ); pTemp->m_flFrame = random->RandomInt( 0, flFrameCount - 1 ); pTemp->m_flFrameMax = flFrameCount - 1; pTemp->die = gpGlobals->curtime + flLife + random->RandomFloat( 0, 4 ); } } //----------------------------------------------------------------------------- // Purpose: Attaches entity to player // Input : client - // modelIndex - // zoffset - // life - //----------------------------------------------------------------------------- void CTempEnts::AttachTentToPlayer( int client, int modelIndex, float zoffset, float life ) { C_LocalTempEntity *pTemp; const model_t *pModel; Vector position; int frameCount; if ( client <= 0 || client > gpGlobals->maxClients ) { Warning("Bad client in AttachTentToPlayer()!\n"); return; } IClientEntity *clientClass = cl_entitylist->GetClientEntity( client ); if ( !clientClass ) { Warning("Couldn't get IClientEntity for %i\n", client ); return; } pModel = modelinfo->GetModel( modelIndex ); if ( !pModel ) { Warning("No model %d!\n", modelIndex); return; } VectorCopy( clientClass->GetAbsOrigin(), position ); position[ 2 ] += zoffset; pTemp = TempEntAllocHigh( position, pModel ); if (!pTemp) { Warning("No temp ent.\n"); return; } pTemp->SetRenderMode( kRenderNormal ); pTemp->SetRenderColorA( 255 ); pTemp->tempent_renderamt = 255; pTemp->m_nRenderFX = kRenderFxNoDissipation; pTemp->clientIndex = client; pTemp->tentOffset[ 0 ] = 0; pTemp->tentOffset[ 1 ] = 0; pTemp->tentOffset[ 2 ] = zoffset; pTemp->die = gpGlobals->curtime + life; pTemp->flags |= FTENT_PLYRATTACHMENT | FTENT_PERSIST; // is the model a sprite? if ( modelinfo->GetModelType( pTemp->GetModel() ) == mod_sprite ) { frameCount = modelinfo->GetModelFrameCount( pModel ); pTemp->m_flFrameMax = frameCount - 1; pTemp->flags |= FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP; pTemp->m_flFrameRate = 10; } else { // no animation support for attached clientside studio models. pTemp->m_flFrameMax = 0; } pTemp->m_flFrame = 0; } //----------------------------------------------------------------------------- // Purpose: Detach entity from player //----------------------------------------------------------------------------- void CTempEnts::KillAttachedTents( int client ) { if ( client <= 0 || client > gpGlobals->maxClients ) { Warning("Bad client in KillAttachedTents()!\n"); return; } FOR_EACH_LL( m_TempEnts, i ) { C_LocalTempEntity *pTemp = m_TempEnts[ i ]; if ( pTemp->flags & FTENT_PLYRATTACHMENT ) { // this TENT is player attached. // if it is attached to this client, set it to die instantly. if ( pTemp->clientIndex == client ) { pTemp->die = gpGlobals->curtime;// good enough, it will die on next tent update. } } } } //----------------------------------------------------------------------------- // Purpose: Create ricochet sprite // Input : *pos - // *pmodel - // duration - // scale - //----------------------------------------------------------------------------- void CTempEnts::RicochetSprite( const Vector &pos, model_t *pmodel, float duration, float scale ) { C_LocalTempEntity *pTemp; pTemp = TempEntAlloc( pos, pmodel ); if (!pTemp) return; pTemp->SetRenderMode( kRenderGlow ); pTemp->m_nRenderFX = kRenderFxNoDissipation; pTemp->SetRenderColorA( 200 ); pTemp->tempent_renderamt = 200; pTemp->m_flSpriteScale = scale; pTemp->flags = FTENT_FADEOUT; pTemp->SetVelocity( vec3_origin ); pTemp->SetLocalOrigin( pos ); pTemp->fadeSpeed = 8; pTemp->die = gpGlobals->curtime; pTemp->m_flFrame = 0; pTemp->SetLocalAnglesDim( Z_INDEX, 45 * random->RandomInt( 0, 7 ) ); } //----------------------------------------------------------------------------- // Purpose: Create blood sprite // Input : *org - // colorindex - // modelIndex - // modelIndex2 - // size - //----------------------------------------------------------------------------- void CTempEnts::BloodSprite( const Vector &org, int r, int g, int b, int a, int modelIndex, int modelIndex2, float size ) { const model_t *model; //Validate the model first if ( modelIndex && (model = modelinfo->GetModel( modelIndex ) ) != NULL ) { C_LocalTempEntity *pTemp; int frameCount = modelinfo->GetModelFrameCount( model ); color32 impactcolor = { r, g, b, a }; //Large, single blood sprite is a high-priority tent if ( ( pTemp = TempEntAllocHigh( org, model ) ) != NULL ) { pTemp->SetRenderMode( kRenderTransTexture ); pTemp->m_nRenderFX = kRenderFxClampMinScale; pTemp->m_flSpriteScale = random->RandomFloat( size / 25, size / 35); pTemp->flags = FTENT_SPRANIMATE; pTemp->m_clrRender = impactcolor; pTemp->tempent_renderamt= pTemp->m_clrRender->a; pTemp->SetVelocity( vec3_origin ); pTemp->m_flFrameRate = frameCount * 4; // Finish in 0.250 seconds pTemp->die = gpGlobals->curtime + (frameCount / pTemp->m_flFrameRate); // Play the whole thing Once pTemp->m_flFrame = 0; pTemp->m_flFrameMax = frameCount - 1; pTemp->bounceFactor = 0; pTemp->SetLocalAnglesDim( Z_INDEX, random->RandomInt( 0, 360 ) ); } } } //----------------------------------------------------------------------------- // Purpose: Create default sprite TE // Input : *pos - // spriteIndex - // framerate - // Output : C_LocalTempEntity //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::DefaultSprite( const Vector &pos, int spriteIndex, float framerate ) { C_LocalTempEntity *pTemp; int frameCount; const model_t *pSprite; // don't spawn while paused if ( gpGlobals->frametime == 0.0 ) return NULL; pSprite = modelinfo->GetModel( spriteIndex ); if ( !spriteIndex || !pSprite || modelinfo->GetModelType( pSprite ) != mod_sprite ) { DevWarning( 1,"No Sprite %d!\n", spriteIndex); return NULL; } frameCount = modelinfo->GetModelFrameCount( pSprite ); pTemp = TempEntAlloc( pos, pSprite ); if (!pTemp) return NULL; pTemp->m_flFrameMax = frameCount - 1; pTemp->m_flSpriteScale = 1.0; pTemp->flags |= FTENT_SPRANIMATE; if ( framerate == 0 ) framerate = 10; pTemp->m_flFrameRate = framerate; pTemp->die = gpGlobals->curtime + (float)frameCount / framerate; pTemp->m_flFrame = 0; pTemp->SetLocalOrigin( pos ); return pTemp; } //----------------------------------------------------------------------------- // Purpose: Create sprite smoke // Input : *pTemp - // scale - //----------------------------------------------------------------------------- void CTempEnts::Sprite_Smoke( C_LocalTempEntity *pTemp, float scale ) { if ( !pTemp ) return; pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->m_nRenderFX = kRenderFxNone; pTemp->SetVelocity( Vector( 0, 0, 30 ) ); int iColor = random->RandomInt(20,35); pTemp->SetRenderColor( iColor, iColor, iColor, 255 ); pTemp->SetLocalOriginDim( Z_INDEX, pTemp->GetLocalOriginDim( Z_INDEX ) + 20 ); pTemp->m_flSpriteScale = scale; pTemp->flags = FTENT_WINDBLOWN; } bool plrIsUnderWater; //----------------------------------------------------------------------------- // Purpose: // Input : pos1 - // angles - // type - //----------------------------------------------------------------------------- void CTempEnts::EjectBrass( const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type ) { if (cl_ejectbrass.GetBool() == false) return; if (!GetActiveWeapon()) return; char shellName[128]; V_snprintf(shellName, sizeof(shellName), "%s", AllocPooledString(GetActiveWeapon()->GetWpnData().iWeaponShellModel)); const model_t *pModel = (model_t *)engine->LoadModel(shellName); if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer) { if (pPlayer->GetActiveWeapon()) pTemp->bounceSound = pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellBounceSound; } pTemp->hitSound = BOUNCE_SHELL; pTemp->m_nBody = 0; pTemp->flags |= (FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024, 1024); //Face forward pTemp->SetAbsAngles(gunAngles); pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout Vector dir; AngleVectors(angles, &dir); dir *= random->RandomFloat(150.0f, 200.0f); if (type == 3) dir /= random->RandomFloat(3.0f, 4.0f); pTemp->SetVelocity(Vector(dir[0] + random->RandomFloat(-64, 64), dir[1] + random->RandomFloat(-64, 64), dir[2] + random->RandomFloat(0, 64))); if (oc_particle_ejectbrass_smoke.GetBool()) { char shellParticle[128]; V_snprintf(shellParticle, sizeof(shellParticle), "%s", AllocPooledString(GetActiveWeapon()->GetWpnData().iWeaponShellParticle)); if (AllocPooledString(GetActiveWeapon()->GetWpnData().iWeaponShellParticle) != AllocPooledString("None")) pTemp->AddParticleEffect(shellParticle); } pTemp->die = gpGlobals->curtime + 3.0f + random->RandomFloat(0.0f, 1.0f); // Add an extra 0-1 secs of life } void CTempEnts::EjectBrass(const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type, C_BaseCombatCharacter *pOwner) { if (cl_ejectbrass.GetBool() == false) return; if (!pOwner) return; if (!pOwner->GetActiveWeapon()) return; const model_t *pModel = (model_t *)engine->LoadModel(pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellModel); if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; if (pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellExhaustParticle != AllocPooledString("None") && pOwner->GetActiveWeapon()->WeaponGetWaterLevel() != 3) Shell_exhaust_Npc(pOwner); pTemp->bounceSound = pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellBounceSound; pTemp->hitSound = BOUNCE_SHELL; pTemp->m_nBody = 0; pTemp->flags |= (FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024, 1024); //Face forward pTemp->SetAbsAngles(gunAngles); pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout Vector dir; AngleVectors(angles, &dir); dir *= random->RandomFloat(150.0f, 200.0f); if (type == 3) dir /= random->RandomFloat(3.0f, 4.0f); pTemp->SetVelocity(Vector(dir[0] + random->RandomFloat(-64, 64), dir[1] + random->RandomFloat(-64, 64), dir[2] + random->RandomFloat(0, 64))); if (oc_particle_ejectbrass_smoke.GetBool() && pOwner->GetActiveWeapon()->WeaponGetWaterLevel() != 3)// && !plrIsUnderWater)//OverCharged { //char shellParticle[128]; //V_snprintf(shellParticle, sizeof(shellParticle), "%s", AllocPooledString(pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellParticle)); if (AllocPooledString(pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellParticle) != AllocPooledString("None")) pTemp->AddParticleEffect(pOwner->GetActiveWeapon()->GetWpnData().iWeaponShellParticle); } pTemp->die = gpGlobals->curtime + 3.0f + random->RandomFloat(0.0f, 1.0f); // Add an extra 0-1 secs of life } void CTempEnts::EjectBrass(const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type, C_BasePlayer *pPlayer) { if (cl_ejectbrass.GetBool() == false) return; if (!pPlayer) return; if (!pPlayer->GetActiveWeapon()) return; //char shellName[128]; //V_snprintf(shellName, sizeof(shellName), "%s", AllocPooledString(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellModel)); const model_t *pModel = (model_t *)engine->LoadModel(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellModel); if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; if (oc_particle_ejectbrass_smoke.GetBool() && pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellExhaustParticle != AllocPooledString("None") && pPlayer->GetWaterLevel() != 3) Shell_exhaust(pPlayer); //char shellSnd[128]; //V_snprintf(shellSnd, sizeof(shellSnd), "%s", AllocPooledString(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellBounceSound)); //DevMsg("%s \n", shellSnd); pTemp->bounceSound = pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellBounceSound; //DevMsg("%s \n", pTemp->bounceSound); pTemp->hitSound = BOUNCE_SHELL; pTemp->m_nBody = 0; pTemp->flags |= (FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024, 1024); //Face forward pTemp->SetAbsAngles(gunAngles); pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout Vector dir; AngleVectors(angles, &dir); dir *= random->RandomFloat(150.0f, 200.0f); if (type == 3) dir /= random->RandomFloat(3.0f, 4.0f); pTemp->SetVelocity(Vector(dir[0] + random->RandomFloat(-64, 64), dir[1] + random->RandomFloat(-64, 64), dir[2] + random->RandomFloat(0, 64))); if (oc_particle_ejectbrass_smoke.GetBool() && pPlayer->GetWaterLevel() != 3)// && !plrIsUnderWater)//OverCharged { //char shellParticle[128]; //V_snprintf(shellParticle, sizeof(shellParticle), "%s", AllocPooledString(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellParticle)); if (AllocPooledString(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellParticle) != AllocPooledString("None")) pTemp->AddParticleEffect(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellParticle); } pTemp->die = gpGlobals->curtime + 3.0f + random->RandomFloat(0.0f, 1.0f); // Add an extra 0-1 secs of life } void CTempEnts::EjectBrass(const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type, C_BaseCombatWeapon *pWeapon) { if (cl_ejectbrass.GetBool() == false) return; if (!pWeapon) return; const model_t *pModel = (model_t *)engine->LoadModel(pWeapon->GetWpnData().iWeaponShellModel); if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; if (oc_particle_ejectbrass_smoke.GetBool() && pWeapon->GetWpnData().iWeaponShellExhaustParticle != AllocPooledString("None") && pWeapon->GetWaterLevel() != 3) Shell_exhaust(pWeapon); pTemp->bounceSound = pWeapon->GetWpnData().iWeaponShellBounceSound; pTemp->hitSound = BOUNCE_SHELL; pTemp->m_nBody = 0; pTemp->flags |= (FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024, 1024); //Face forward pTemp->SetAbsAngles(gunAngles); pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout Vector dir; AngleVectors(angles, &dir); dir *= random->RandomFloat(150.0f, 200.0f); if (type == 3) dir /= random->RandomFloat(3.0f, 4.0f); pTemp->SetVelocity(Vector(dir[0] + random->RandomFloat(-64, 64), dir[1] + random->RandomFloat(-64, 64), dir[2] + random->RandomFloat(0, 64))); if (oc_particle_ejectbrass_smoke.GetBool() && pWeapon->GetWaterLevel() != 3) { if (AllocPooledString(pWeapon->GetWpnData().iWeaponShellParticle) != AllocPooledString("None")) pTemp->AddParticleEffect(pWeapon->GetWpnData().iWeaponShellParticle); } pTemp->die = gpGlobals->curtime + 3.0f + random->RandomFloat(0.0f, 1.0f); } //OverCharged///////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- // Purpose: // Input : pos1 - // angles - // type - //----------------------------------------------------------------------------- void CTempEnts::EjectBrassMag(const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, int type) { if (cl_ejectbrass.GetBool() == false) return; const model_t *pModel = m_Mag[type]; if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; //Keep track of shell type // if (type == 3) // { pTemp->hitSound = BOUNCE_MAG; // } /* else { pTemp->hitSound = BOUNCE_SHELL; }*/ pTemp->m_nBody = 1; //pTemp->flags |= (FTENT_COLLIDEALL | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE | FTENT_COLLISIONGROUP | FTENT_COLLIDEPROPS); pTemp->flags |= (FTENT_FADEOUT | FTENT_GRAVITY); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024, 1024); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024, 1024); //Face forward pTemp->SetAbsAngles(gunAngles); /*pTemp->SetSolid(SOLID_BBOX); pTemp->SetCollisionBounds(vec3_origin, vec3_origin); pTemp->SetCollisionGroup(COLLISION_GROUP_WEAPON);*/ pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout Vector dir; AngleVectors(angles, &dir); dir *= random->RandomFloat(150.0f, 200.0f); pTemp->SetVelocity(Vector(dir[0] + random->RandomFloat(-64, 64), dir[1] + random->RandomFloat(-64, 64), dir[2] + random->RandomFloat(0, 64))); // DispatchParticleEffect( "weapon_muzzle_flash_sparks4", dir, gunAngles ); // DispatchParticleEffect( "slime_splash_01", pos1, angles );// slime_splash_01 // C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); // DispatchParticleEffect( "shell_eject_smoke_flash", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), "1", true); if (oc_particle_ejectbrass_smoke.GetBool() == true)//OverCharged { pTemp->AddParticleEffect("shell_exhaust_smoke"); } // pTemp->AddParticleEffect("1trail"); //pTemp->AddParticleEffect("shell_fx_main"); //pTemp->AddParticleEffect("ExtinguisherJet"); pTemp->die = gpGlobals->curtime + 5.0f + random->RandomFloat(0.0f, 1.0f); // Add an extra 0-1 secs of life } ///////////////////////////////////////////////////////////////////////////// void CTempEnts::CreateSphere(const Vector &pos1, const QAngle &gunAngles, int type, C_BasePlayer *pPlayer) { if (cl_ejectbrass.GetBool() == false) return; if (!pPlayer) return; if (!pPlayer->GetActiveWeapon()) return; const model_t *pModel = (model_t *)engine->LoadModel(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellModel); if (pModel == NULL) return; C_LocalTempEntity *pTemp = TempEntAlloc(pos1, (model_t *)pModel); if (pTemp == NULL) return; if (oc_particle_ejectbrass_smoke.GetBool() && pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellExhaustParticle != AllocPooledString("None") && pPlayer->GetWaterLevel() != 3) Shell_exhaust(pPlayer); pTemp->SetParent(pPlayer->GetViewModel()); pTemp->SetOwnerEntity(pPlayer->GetViewModel()); pTemp->FollowEntity(pPlayer->GetViewModel()); pTemp->bounceSound = pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellBounceSound; pTemp->hitSound = BOUNCE_SHELL; pTemp->m_nBody = 0; pTemp->flags |= (FTENT_FADEOUT); pTemp->SetAbsAngles(gunAngles); pTemp->SetRenderMode(kRenderNormal); pTemp->tempent_renderamt = 255; // Set this for fadeout if (oc_particle_ejectbrass_smoke.GetBool() && pPlayer->GetWaterLevel() != 3)// && !plrIsUnderWater)//OverCharged { if (AllocPooledString(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellParticle) != AllocPooledString("None")) pTemp->AddParticleEffect(pPlayer->GetActiveWeapon()->GetWpnData().iWeaponShellParticle); } pTemp->die = gpGlobals->curtime + 3.0f + random->RandomFloat(0.0f, 1.0f); // Add an extra 0-1 secs of life } //----------------------------------------------------------------------------- // Purpose: Create some simple physically simulated models //----------------------------------------------------------------------------- C_LocalTempEntity * CTempEnts::SpawnTempModel( const model_t *pModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, float flLifeTime, int iFlags ) { Assert( pModel ); // Alloc a new tempent C_LocalTempEntity *pTemp = TempEntAlloc( vecOrigin, pModel ); if ( !pTemp ) return NULL; pTemp->SetAbsAngles( vecAngles ); pTemp->m_nBody = 0; pTemp->flags |= iFlags; pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-255,255); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-255,255); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-255,255); pTemp->SetRenderMode( kRenderNormal ); pTemp->tempent_renderamt = 255; pTemp->SetVelocity( vecVelocity ); pTemp->die = gpGlobals->curtime + flLifeTime; return pTemp; } #include "c_basehlcombatweapon.h" float PosX1; float PosY1; float PosZ1; float DynX1; float DynY1; float DynZ1; static ConVar oc_weapon_dual_pistols_tracers_x("oc_weapon_dual_pistols_tracers_x", "0.0", FCVAR_ARCHIVE); static ConVar oc_weapon_dual_pistols_tracers_y("oc_weapon_dual_pistols_tracers_y", "0.0", FCVAR_ARCHIVE); static ConVar oc_weapon_dual_pistols_tracers_z("oc_weapon_dual_pistols_tracers_z", "0.0", FCVAR_ARCHIVE); static ConVar oc_adjust_tracers_dynamic_offset_x("oc_adjust_tracers_dynamic_offset_x", "0.0", FCVAR_REPLICATED); static ConVar oc_adjust_tracers_dynamic_offset_y("oc_adjust_tracers_dynamic_offset_y", "0.0", FCVAR_REPLICATED); static ConVar oc_adjust_tracers_dynamic_offset_z("oc_adjust_tracers_dynamic_offset_z", "0.0", FCVAR_REPLICATED); static ConVar oc_adjust_tracers_dynamic_offset("oc_adjust_tracers_dynamic_offset", "0", FCVAR_REPLICATED); static ConVar oc_adjust_weapon_tracers_offset("oc_adjust_weapon_tracers_offset", "0", FCVAR_REPLICATED); static ConVar oc_adjust_weapon_tracers_offset_x("oc_adjust_weapon_tracers_offset_x", "0", FCVAR_REPLICATED); static ConVar oc_adjust_weapon_tracers_offset_y("oc_adjust_weapon_tracers_offset_y", "0", FCVAR_REPLICATED); static ConVar oc_adjust_weapon_tracers_offset_z("oc_adjust_weapon_tracers_offset_z", "0", FCVAR_REPLICATED); static ConVar oc_test_adjust_weapon_tracers2_offset("oc_test_adjust_weapon_tracers2_offset", "0", FCVAR_REPLICATED); static ConVar oc_test_adjust_weapon_tracers2_offset_x("oc_test_adjust_weapon_tracers2_offset_x", "0", FCVAR_REPLICATED); static ConVar oc_test_adjust_weapon_tracers2_offset_y("oc_test_adjust_weapon_tracers2_offset_y", "0", FCVAR_REPLICATED); static ConVar oc_test_adjust_weapon_tracers2_offset_z("oc_test_adjust_weapon_tracers2_offset_z", "0", FCVAR_REPLICATED); extern ConVar oc_muzzle_tracer_x; extern ConVar oc_muzzle_tracer_y; extern ConVar oc_muzzle_tracer_z; void CTempEnts::UpdateMuzzlePosition(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("TracerLocal", VPROF_BUDGETGROUP_PARTICLE_RENDERING); //CSmartPtr pSimple = CLocalSpaceEmitter::Create("TracerLocal", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); Vector forward(1,0,0), up(0,0,1), right(0,1,0), Dest; //NOTENOTE: All coords are in local space Vector forwardD(1, 0, 0), upD(0, 0, 1), rightD(0, 1, 0); //NOTENOTE: All coords are in local space //pSimple->SetDrawBeforeViewModel(true); Vector origin; QAngle angles, DestAngles; QAngle MAngle; Vector vecLightOrigin, ForTracers; Vector Dyn; QAngle DAngle; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; C_BaseViewModel *pVm = pPlayer->GetViewModel(); if (pVm == NULL) return; C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; if (pWeapon != NULL) { if (pWeapon->GetWpnData().ProjectilePosition == NULL) return; if ((cvar->FindVar("oc_adjust_weapon_tracers_offset")->GetInt() == 0)) { PosX1 = pWeapon->GetWpnData().ProjectilePosition.x; PosY1 = pWeapon->GetWpnData().ProjectilePosition.y; PosZ1 = pWeapon->GetWpnData().ProjectilePosition.z; if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { DynX1 = pWeapon->GetWpnData().ParticleTracerPosition.x; DynY1 = pWeapon->GetWpnData().ParticleTracerPosition.y; DynZ1 = pWeapon->GetWpnData().ParticleTracerPosition.z; } } else if ((cvar->FindVar("oc_adjust_weapon_tracers_offset")->GetInt() == 1)) { PosX1 = cvar->FindVar("oc_adjust_weapon_tracers_offset_x")->GetFloat(); PosY1 = cvar->FindVar("oc_adjust_weapon_tracers_offset_y")->GetFloat(); PosZ1 = cvar->FindVar("oc_adjust_weapon_tracers_offset_z")->GetFloat(); } if ((cvar->FindVar("oc_adjust_tracers_dynamic_offset")->GetInt() == 0)) { if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { DynX1 = pWeapon->GetWpnData().ParticleTracerPosition.x; DynY1 = pWeapon->GetWpnData().ParticleTracerPosition.y; DynZ1 = pWeapon->GetWpnData().ParticleTracerPosition.z; } } else if ((cvar->FindVar("oc_adjust_tracers_dynamic_offset")->GetInt() == 1)) { if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { DynX1 = cvar->FindVar("oc_adjust_tracers_dynamic_offset_x")->GetFloat(); DynY1 = cvar->FindVar("oc_adjust_tracers_dynamic_offset_y")->GetFloat(); DynZ1 = cvar->FindVar("oc_adjust_tracers_dynamic_offset_z")->GetFloat(); } } // Get our attachment's transformation matrix //if ((FClassnameIs(pWeapon, "weapon_dual_pistols"))) if (pWeapon->thisType == TYPE_DUAL_PISTOLS || pWeapon->thisType == TYPE_DUAL_MACHINEGUNS) { if (cvar->FindVar("oc_use_second_ballel")->GetInt() == 0) { int iAttachment = pVm->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachment2);//pVm->LookupAttachment("muzzle1"); pVm->GetAttachment(iAttachment, vecLightOrigin, MAngle); } else { int iAttachment2 = pVm->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachment);//pVm->LookupAttachment("muzzle"); pVm->GetAttachment(iAttachment2, vecLightOrigin, MAngle); } } else { int iAttachment = pVm->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachment);//pVm->LookupAttachment("muzzle"); if (iAttachment < 0) { int iAttachment0 = 1; if (iAttachment0 < 0) { int iAttachment3 = 2; pVm->GetAttachment(iAttachment3, vecLightOrigin, MAngle); if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { pVm->GetAttachment(iAttachment3, Dyn, DAngle); } } else { pVm->GetAttachment(iAttachment0, vecLightOrigin, MAngle); if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { pVm->GetAttachment(iAttachment0, Dyn, DAngle); } } } else { pVm->GetAttachment(iAttachment, vecLightOrigin, MAngle); if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { pVm->GetAttachment(iAttachment, Dyn, DAngle); } } } AngleVectors(MAngle, &forward, &right, &up); if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { AngleVectors(DAngle, &forwardD, &rightD, &upD); } //if ((FClassnameIs(pWeapon, "weapon_dual_pistols"))) if (pWeapon->thisType == TYPE_DUAL_PISTOLS || pWeapon->thisType == TYPE_DUAL_MACHINEGUNS) { ForTracers = vecLightOrigin; ForTracers += forward * oc_weapon_dual_pistols_tracers_x.GetFloat(); ForTracers += right * oc_weapon_dual_pistols_tracers_y.GetFloat(); ForTracers += up * oc_weapon_dual_pistols_tracers_z.GetFloat(); cvar->FindVar("oc_muzzle_tracer_x")->SetValue(ForTracers.x); cvar->FindVar("oc_muzzle_tracer_y")->SetValue(ForTracers.y); cvar->FindVar("oc_muzzle_tracer_z")->SetValue(ForTracers.z); cvar->FindVar("oc_muzzle_vector_x")->SetValue(vecLightOrigin.x); cvar->FindVar("oc_muzzle_vector_y")->SetValue(vecLightOrigin.y); cvar->FindVar("oc_muzzle_vector_z")->SetValue(vecLightOrigin.z); //engine->ServerCmd(VarArgs("MuzzleVectors %f %f %f %f %f %f\n", ForTracers.x, ForTracers.y, ForTracers.z, vecLightOrigin.x, vecLightOrigin.y, vecLightOrigin.z), false); if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { cvar->FindVar("oc_muzzle_dynamic_vector_x")->SetValue(vecLightOrigin.x); cvar->FindVar("oc_muzzle_dynamic_vector_y")->SetValue(vecLightOrigin.y); cvar->FindVar("oc_muzzle_dynamic_vector_z")->SetValue(vecLightOrigin.z); } } else { ForTracers = vecLightOrigin; ForTracers += forward * PosX1; ForTracers += right * PosY1; ForTracers += up *PosZ1; if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { Dyn += forwardD *DynX1; Dyn += rightD *DynY1; Dyn += upD *DynZ1; } } } //if (!(FClassnameIs(pWeapon, "weapon_dual_pistols"))) if (!(pWeapon->thisType == TYPE_DUAL_PISTOLS) && !(pWeapon->thisType == TYPE_DUAL_MACHINEGUNS)) { if (!pWeapon->IsScopeSighted()) { cvar->FindVar("oc_muzzle_tracer_x")->SetValue(ForTracers.x); cvar->FindVar("oc_muzzle_tracer_y")->SetValue(ForTracers.y); cvar->FindVar("oc_muzzle_tracer_z")->SetValue(ForTracers.z); cvar->FindVar("oc_muzzle_vector_x")->SetValue(vecLightOrigin.x); cvar->FindVar("oc_muzzle_vector_y")->SetValue(vecLightOrigin.y); cvar->FindVar("oc_muzzle_vector_z")->SetValue(vecLightOrigin.z); //engine->ServerCmd(VarArgs("MuzzleVectors %f %f %f %f %f %f\n", ForTracers.x, ForTracers.y, ForTracers.z, vecLightOrigin.x, vecLightOrigin.y, vecLightOrigin.z), false); } else if (pWeapon->IsScopeSighted())// || (cvar->FindVar("oc_state_IRsight_on")->GetInt() == 1)) { Vector vForward, vRight, vUp, vThrowPos, Muzzle;//MY(oc_InScope_weapon_oicw_muzzleflash_position_x.GetFloat(), oc_InScope_weapon_oicw_muzzleflash_position_y.GetFloat(), oc_InScope_weapon_oicw_muzzleflash_position_z.GetFloat()); QAngle pAngles; pPlayer->EyeVectors(&vForward, &vRight, &vUp); pAngles.x = pPlayer->EyeAngles().x;// *oc_InScope_weapon_muzzleflash_angle_constant.GetFloat(); pAngles.y = pPlayer->EyeAngles().y;// *oc_InScope_weapon_muzzleflash_angle_constant.GetFloat(); pAngles.z = oc_InScope_weapon_muzzleflash_angle_z.GetFloat(); vThrowPos = pPlayer->EyePosition(); //vThrowPos = Muzzle2; vThrowPos += vForward * oc_InScope_weapon_tracers_position_x.GetFloat(); vThrowPos += vRight * oc_InScope_weapon_tracers_position_y.GetFloat(); vThrowPos += vUp * oc_InScope_weapon_tracers_position_z.GetFloat(); cvar->FindVar("oc_muzzle_tracer_x")->SetValue(vThrowPos.x); cvar->FindVar("oc_muzzle_tracer_y")->SetValue(vThrowPos.y); cvar->FindVar("oc_muzzle_tracer_z")->SetValue(vThrowPos.z); cvar->FindVar("oc_muzzle_vector_x")->SetValue(vThrowPos.x); cvar->FindVar("oc_muzzle_vector_y")->SetValue(vThrowPos.y); cvar->FindVar("oc_muzzle_vector_z")->SetValue(vThrowPos.z); //engine->ServerCmd(VarArgs("MuzzleVectors %f %f %f %f %f %f\n", vThrowPos.x, vThrowPos.y, vThrowPos.z, vThrowPos.x, vThrowPos.y, vThrowPos.z), false); //engine->ClientCmd_Unrestricted //engine->ServerCmdKeyValues } if ((cvar->FindVar("oc_weapons_enable_dynamic_bullets")->GetInt() == 1)) { cvar->FindVar("oc_muzzle_dynamic_vector_x")->SetValue(Dyn.x); cvar->FindVar("oc_muzzle_dynamic_vector_y")->SetValue(Dyn.y); cvar->FindVar("oc_muzzle_dynamic_vector_z")->SetValue(Dyn.z); } } } void CTempEnts::MuzzleFlashSecondary(const char *name, int colR, int colG, int colB, int type, ClientEntityHandle_t hEntity, int attachmentIndex, bool firstPerson) { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer && firstPerson) { MuzzleLightCallBack(); } C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; if (firstPerson) { if (oc_muzzleflash_light_plr.GetInt() == 1) MuzzleflashCreatePlayerLight(hEntity); if (oc_particle_muzzleflashes.GetInt()) { MuzzleFlash_General_Player_Secondary_Particle_Effect(name, colR, colG, colB, hEntity, attachmentIndex); } else { CEffectData data; if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) data.m_hEntity = pWeapon; else data.m_hEntity = hEntity; data.m_nAttachmentIndex = attachmentIndex; data.m_flScale = 1.0f; data.m_fFlags = type; data.m_bCustomColors = !pWeapon->GetWpnData().oldFlashTypeTP; DispatchEffect("MuzzleFlash", data); } } else { if (oc_muzzleflash_light_npc.GetInt() == 1) MuzzleflashCreateNPCLight(hEntity); if (oc_particle_muzzleflashes.GetInt()) { MuzzleFlash_General_NPC_Secondary_Particle_Effect(name, colR, colG, colB, hEntity, attachmentIndex); } else { CEffectData data; data.m_hEntity = hEntity; data.m_nAttachmentIndex = attachmentIndex; data.m_flScale = 1.0f; data.m_fFlags = type; data.m_bCustomColors = false; DispatchEffect("MuzzleFlash", data); } } } //----------------------------------------------------------------------------- // Purpose: // Input : type - // entityIndex - // attachmentIndex - // firstPerson - //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash(const char *name, int colR, int colG, int colB, int type, ClientEntityHandle_t hEntity, int attachmentIndex, bool firstPerson) { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer && firstPerson) { MuzzleLightCallBack(); } if (firstPerson) { C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; if (oc_muzzleflash_light_plr.GetInt() == 1) MuzzleflashCreatePlayerLight(hEntity); //if (oc_particle_muzzleflashes.GetInt() == 1) if (/*type == -1 && */oc_particle_muzzleflashes.GetInt()) { MuzzleFlash_General_Player_Particle_Effect(name, colR, colG, colB, hEntity, attachmentIndex); } else { //MuzzleFlash_SMG1_Player(hEntity, attachmentIndex); CEffectData data; if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) data.m_hEntity = pWeapon; else data.m_hEntity = hEntity; int iAttachment = attachmentIndex; if (pWeapon) { if (pWeapon->iMuzzle == 2) { if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) iAttachment = pWeapon->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachment2); else iAttachment = pPlayer->GetViewModel()->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachment2);//pPlayer->GetViewModel()->LookupAttachment("muzzle1"); } if (pWeapon->m_bSilenced)//(cvar->FindVar("oc_is_weapon_silenced")->GetInt() == 1) { if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) iAttachment = pWeapon->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachmentSilencer); else iAttachment = pPlayer->GetViewModel()->LookupAttachment(pWeapon->GetWpnData().MuzzleAttachmentSilencer); } } data.m_nAttachmentIndex = iAttachment; data.m_flScale = 1.0f; data.m_fFlags = type; data.m_bCustomColors = pWeapon->GetWpnData().oldFlashTypeTP;// !pWeapon->GetWpnData().oldFlashTypeTP; DispatchEffect("MuzzleFlash", data); /*Vector pos1 = Vector(0, 0, 0); QAngle angles = QAngle(0,0,0); tempents->MuzzleFlash(pos1, angles, type, hEntity, firstPerson, attachmentIndex);*/ } } else { if (oc_muzzleflash_light_npc.GetInt() == 1) MuzzleflashCreateNPCLight(hEntity); //if (oc_particle_muzzleflashes.GetInt() == 1) if (/*type == -1 && */oc_particle_muzzleflashes.GetInt()) { MuzzleFlash_General_NPC_Particle_Effect(name, colR, colG, colB, hEntity, attachmentIndex); } else { //MuzzleFlash_SMG1_NPC(hEntity, attachmentIndex); CEffectData data; data.m_hEntity = hEntity; data.m_nAttachmentIndex = attachmentIndex; data.m_flScale = 1.0f; data.m_fFlags = type; data.m_bCustomColors = false; DispatchEffect("MuzzleFlash", data); /*Vector pos1 = Vector(0, 0, 0); QAngle angles = QAngle(0,0,0); tempents->MuzzleFlash(pos1, angles, type, hEntity, firstPerson, attachmentIndex);*/ } } } void CTempEnts::MuzzleflashCreatePlayerLight(ClientEntityHandle_t hEntity) { C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle(hEntity); if (!pEnt) return; int index = pEnt->index; //pEnt->CreateMuzzleFlashLight(); C_BaseViewModel *pVM = (C_BaseViewModel*)(pEnt); if (pVM) { C_BasePlayer *pPlayer = ToBasePlayer(pVM->GetOwner()); if (pPlayer && pPlayer->GetActiveWeapon() && pPlayer->GetActiveWeapon()->GetWpnData().AllowMuzzleFlashDLight) { pPlayer->dlightKey = index; Vector origin; pPlayer->GetActiveWeapon()->GetAttachment(pPlayer->GetActiveWeapon()->m_bSilenced ? "muzzle_sil" : pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightAttachment, origin); pPlayer->mfEl = effects->CL_AllocDlight(index); //dlight_t *el = effects->CL_AllocDlight(index); float radius = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightRadius * (engine->MapHasHDRLighting() ? 1 : 0.3); int red = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightR; int green = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightG; int blue = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightB; int exp = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightExponent; if (cvar->FindVar("oc_state_InSecondFire")->GetInt() == 1) { exp = 0; red *= 0.1f; green *= 0.1f; blue *= 0.1f; } bool illum = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightNoModelIllumination; float decay = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightDecayTime; float lifeTime = pPlayer->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightLifeTime; if (pPlayer->mfEl) { pPlayer->mfEl->key = index; pPlayer->mfEl->origin = origin; pPlayer->mfEl->color.r = red; pPlayer->mfEl->color.g = green; pPlayer->mfEl->color.b = blue; pPlayer->mfEl->color.exponent = exp; if (illum) pPlayer->mfEl->flags |= DLIGHT_NO_MODEL_ILLUMINATION; pPlayer->mfEl->radius = random->RandomInt(radius - 30.f, radius + 30.f); pPlayer->mfEl->decay = pPlayer->mfEl->radius / decay;// /0.3f pPlayer->mfEl->die = gpGlobals->curtime + lifeTime; } } } } void CTempEnts::MuzzleflashCreateNPCLight(ClientEntityHandle_t hEntity) { C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle(hEntity); if (!pEnt) return; C_BaseCombatCharacter *pCharacter = ToBaseCombatCharacter(pEnt->GetOwnerEntity()); int index = pEnt->index; if (pCharacter && pCharacter->IsNPC()) { if (pCharacter->GetActiveWeapon() && pCharacter->GetActiveWeapon()->GetWpnData().AllowMuzzleFlashDLightNpc) { Vector origin; pCharacter->GetActiveWeapon()->GetAttachment(pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightAttachmentNpc, origin); dlight_t *el = effects->CL_AllocDlight(index); float radius = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightRadiusNpc * (engine->MapHasHDRLighting() ? 1 : 0.3); //(engine->MapHasHDRLighting() ? 2 : 1); int red = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightRNpc; int green = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightGNpc; int blue = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightBNpc; int exp = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightExponentNpc; bool illum = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightNoModelIlluminationNpc; float decay = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightDecayTimeNpc; float lifeTime = pCharacter->GetActiveWeapon()->GetWpnData().iMuzzleFlashLightLifeTimeNpc; if (el) { el->origin = origin;// pCharacter->GetActiveWeapon()->GetAbsOrigin(); el->key = index; el->color.r = red; el->color.g = green; el->color.b = blue; el->color.exponent = exp; if (illum) el->flags |= DLIGHT_NO_MODEL_ILLUMINATION; el->radius = random->RandomInt(radius - 30.f, radius + 30.f); el->decay = el->radius / decay;// /0.3f el->die = gpGlobals->curtime + lifeTime; } } } } void CTempEnts::MuzzleflashCreateWeaponLight(ClientEntityHandle_t hEntity) { C_BaseCombatWeapon *pWeapon = static_cast(ClientEntityList().GetBaseEntityFromHandle(hEntity)); if (!pWeapon) return; int index = pWeapon->index; if (pWeapon) { if (pWeapon->GetWpnData().AllowMuzzleFlashDLightNpc) { Vector origin; pWeapon->GetAttachment(pWeapon->GetWpnData().iMuzzleFlashLightAttachmentNpc, origin); dlight_t *el = effects->CL_AllocDlight(index); float radius = pWeapon->GetWpnData().iMuzzleFlashLightRadiusNpc * (engine->MapHasHDRLighting() ? 1 : 0.3); //(engine->MapHasHDRLighting() ? 2 : 1); int red = pWeapon->GetWpnData().iMuzzleFlashLightRNpc; int green = pWeapon->GetWpnData().iMuzzleFlashLightGNpc; int blue = pWeapon->GetWpnData().iMuzzleFlashLightBNpc; int exp = pWeapon->GetWpnData().iMuzzleFlashLightExponentNpc; bool illum = pWeapon->GetWpnData().iMuzzleFlashLightNoModelIlluminationNpc; float decay = pWeapon->GetWpnData().iMuzzleFlashLightDecayTimeNpc; float lifeTime = pWeapon->GetWpnData().iMuzzleFlashLightLifeTimeNpc; if (el) { el->origin = origin;// pWeapon->GetAbsOrigin(); el->key = index; el->color.r = red; el->color.g = green; el->color.b = blue; el->color.exponent = exp; if (illum) el->flags |= DLIGHT_NO_MODEL_ILLUMINATION; el->radius = random->RandomInt(radius - 30.f, radius + 30.f); el->decay = el->radius / decay;// /0.3f el->die = gpGlobals->curtime + lifeTime; } } } } //----------------------------------------------------------------------------- // Purpose: Play muzzle flash // Input : *pos1 - // type - //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash( const Vector& pos1, const QAngle& angles, int type, ClientEntityHandle_t hEntity, bool firstPerson, int attachmentIndex ) { #ifdef CSTRIKE_DLL return; #else if (attachmentIndex == 0) attachmentIndex = 1; if (type <= 0) type = 2; //NOTENOTE: This function is becoming obsolete as the muzzles are moved over to being local to attachments switch ( type ) { // // Shotgun // case MUZZLEFLASH_SHOTGUN: if ( firstPerson ) { MuzzleFlash_Shotgun_Player(hEntity, attachmentIndex); } else { MuzzleFlash_Shotgun_NPC(hEntity, attachmentIndex); } break; // UNDONE: These need their own effects/sprites. For now use the pistol // SMG1 case MUZZLEFLASH_SMG1: if ( firstPerson ) { MuzzleFlash_SMG1_Player(hEntity, attachmentIndex); } else { MuzzleFlash_SMG1_NPC(hEntity, attachmentIndex); } break; // SMG2 case MUZZLEFLASH_SMG2: case MUZZLEFLASH_PISTOL: if ( firstPerson ) { MuzzleFlash_Pistol_Player(hEntity, attachmentIndex); } else { MuzzleFlash_Pistol_NPC(hEntity, attachmentIndex); } break; case MUZZLEFLASH_COMBINE: if ( firstPerson ) { //FIXME: These should go away MuzzleFlash_Combine_Player(hEntity, attachmentIndex); } else { //FIXME: These should go away MuzzleFlash_Combine_NPC(hEntity, attachmentIndex); } break; case 7: if (firstPerson) { //FIXME: These should go away MuzzleFlash_Combine_Player(hEntity, attachmentIndex); } else { //FIXME: These should go away MuzzleFlash_Combine_NPC(hEntity, attachmentIndex); } break; default: // There's no supported muzzle flash for the type specified! Assert(0); break; } #endif } //----------------------------------------------------------------------------- // Purpose: Create explosion sprite // Input : *pTemp - // scale - // flags - //----------------------------------------------------------------------------- void CTempEnts::Sprite_Explode( C_LocalTempEntity *pTemp, float scale, int flags ) { if ( !pTemp ) return; if ( flags & TE_EXPLFLAG_NOADDITIVE ) { // solid sprite pTemp->SetRenderMode( kRenderNormal ); pTemp->SetRenderColorA( 255 ); } else if( flags & TE_EXPLFLAG_DRAWALPHA ) { // alpha sprite pTemp->SetRenderMode( kRenderTransAlpha ); pTemp->SetRenderColorA( 180 ); } else { // additive sprite pTemp->SetRenderMode( kRenderTransAdd ); pTemp->SetRenderColorA( 180 ); } if ( flags & TE_EXPLFLAG_ROTATE ) { pTemp->SetLocalAnglesDim( Z_INDEX, random->RandomInt( 0, 360 ) ); } pTemp->m_nRenderFX = kRenderFxNone; pTemp->SetVelocity( Vector( 0, 0, 8 ) ); pTemp->SetRenderColor( 255, 255, 255 ); pTemp->SetLocalOriginDim( Z_INDEX, pTemp->GetLocalOriginDim( Z_INDEX ) + 10 ); pTemp->m_flSpriteScale = scale; } enum { SHELL_NONE = 0, SHELL_SMALL, SHELL_BIG, SHELL_SHOTGUN, }; //----------------------------------------------------------------------------- // Purpose: Clear existing temp entities //----------------------------------------------------------------------------- void CTempEnts::Clear( void ) { FOR_EACH_LL( m_TempEnts, i ) { C_LocalTempEntity *p = m_TempEnts[ i ]; m_TempEntsPool.Free( p ); } m_TempEnts.RemoveAll(); g_BreakableHelper.Clear(); } C_LocalTempEntity *CTempEnts::FindTempEntByID( int nID, int nSubID ) { // HACK HACK: We're using skin and hitsounds as a hacky way to store an ID and sub-ID for later identification FOR_EACH_LL( m_TempEnts, i ) { C_LocalTempEntity *p = m_TempEnts[ i ]; if ( p && p->m_nSkin == nID && p->hitSound == nSubID ) { return p; } } return NULL; } //----------------------------------------------------------------------------- // Purpose: Allocate temp entity ( normal/low priority ) // Input : *org - // *model - // Output : C_LocalTempEntity //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::TempEntAlloc( const Vector& org, const model_t *model ) { C_LocalTempEntity *pTemp; if ( !model ) { DevWarning( 1, "Can't create temporary entity with NULL model!\n" ); return NULL; } pTemp = TempEntAlloc(); if ( !pTemp ) { DevWarning( 1, "Overflow %d temporary ents!\n", MAX_TEMP_ENTITIES ); return NULL; } m_TempEnts.AddToTail( pTemp ); pTemp->Prepare( model, gpGlobals->curtime ); pTemp->priority = TENTPRIORITY_LOW; pTemp->SetAbsOrigin( org ); pTemp->m_RenderGroup = RENDER_GROUP_OTHER; pTemp->AddToLeafSystem( pTemp->m_RenderGroup ); if ( CommandLine()->CheckParm( "-tools" ) != NULL ) { #ifdef _DEBUG static bool first = true; if ( first ) { Msg( "Currently not recording tempents, since recording them as entites causes them to be deleted as entities, even though they were allocated through the tempent pool. (crash)\n" ); first = false; } #endif // ClientEntityList().AddNonNetworkableEntity( pTemp ); } return pTemp; } //----------------------------------------------------------------------------- // Purpose: // Output : C_LocalTempEntity //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::TempEntAlloc() { if ( m_TempEnts.Count() >= MAX_TEMP_ENTITIES ) return NULL; C_LocalTempEntity *pTemp = m_TempEntsPool.AllocZero(); return pTemp; } void CTempEnts::TempEntFree( int index ) { C_LocalTempEntity *pTemp = m_TempEnts[ index ]; if ( pTemp ) { // Remove from the active list. m_TempEnts.Remove( index ); // Cleanup its data. pTemp->RemoveFromLeafSystem(); // Remove the tempent from the ClientEntityList before removing it from the pool. if ( ( pTemp->flags & FTENT_CLIENTSIDEPARTICLES ) ) { // Stop the particle emission if this hasn't happened already - collision or system timing out on its own. if ( !pTemp->m_bParticleCollision ) { pTemp->ParticleProp()->StopEmission(); } ClientEntityList().RemoveEntity( pTemp->GetRefEHandle() ); } pTemp->OnRemoveTempEntity(); m_TempEntsPool.Free( pTemp ); } } // Free the first low priority tempent it finds. bool CTempEnts::FreeLowPriorityTempEnt() { int next = 0; for( int i = m_TempEnts.Head(); i != m_TempEnts.InvalidIndex(); i = next ) { next = m_TempEnts.Next( i ); C_LocalTempEntity *pActive = m_TempEnts[ i ]; if ( pActive->priority == TENTPRIORITY_LOW ) { TempEntFree( i ); return true; } } return false; } //----------------------------------------------------------------------------- // Purpose: Allocate a temp entity, if there are no slots, kick out a low priority // one if possible // Input : *org - // *model - // Output : C_LocalTempEntity //----------------------------------------------------------------------------- C_LocalTempEntity *CTempEnts::TempEntAllocHigh( const Vector& org, const model_t *model ) { C_LocalTempEntity *pTemp; if ( !model ) { DevWarning( 1, "temporary ent model invalid\n" ); return NULL; } pTemp = TempEntAlloc(); if ( !pTemp ) { // no temporary ents free, so find the first active low-priority temp ent // and overwrite it. FreeLowPriorityTempEnt(); pTemp = TempEntAlloc(); } if ( !pTemp ) { // didn't find anything? The tent list is either full of high-priority tents // or all tents in the list are still due to live for > 10 seconds. DevWarning( 1,"Couldn't alloc a high priority TENT (max %i)!\n", MAX_TEMP_ENTITIES ); return NULL; } m_TempEnts.AddToTail( pTemp ); pTemp->Prepare( model, gpGlobals->curtime ); pTemp->priority = TENTPRIORITY_HIGH; pTemp->SetLocalOrigin( org ); pTemp->m_RenderGroup = RENDER_GROUP_OTHER; pTemp->AddToLeafSystem( pTemp->m_RenderGroup ); if ( CommandLine()->CheckParm( "-tools" ) != NULL ) { ClientEntityList().AddNonNetworkableEntity( pTemp ); } return pTemp; } //----------------------------------------------------------------------------- // Purpose: Play sound when temp ent collides with something // Input : *pTemp - // damp - //----------------------------------------------------------------------------- void CTempEnts::PlaySound ( C_LocalTempEntity *pTemp, float damp ) { const char *soundname = NULL; float fvol; bool isshellcasing = false; int zvel; switch ( pTemp->hitSound ) { default: return; // null sound case BOUNCE_GLASS: { soundname = "Bounce.Glass"; } break; case BOUNCE_METAL: { soundname = "Bounce.Metal"; } break; case BOUNCE_FLESH: { soundname = "Bounce.Flesh"; } break; case BOUNCE_WOOD: { soundname = "Bounce.Wood"; } break; case BOUNCE_SHRAP: { soundname = "Bounce.Shrapnel"; } break; case BOUNCE_SHOTSHELL: { soundname = "Bounce.ShotgunShell"; isshellcasing = true; // shell casings have different playback parameters } break; case BOUNCE_SHELL: { soundname = pTemp->bounceSound; //soundname = "Bounce.Shell"; isshellcasing = true; // shell casings have different playback parameters } break; case BOUNCE_MAG: { soundname = "Bounce.Mag"; isshellcasing = true; // shell casings have different playback parameters } break; case BOUNCE_CONCRETE: { soundname = "Bounce.Concrete"; } break; #ifdef CSTRIKE_DLL case TE_PISTOL_SHELL: { soundname = "Bounce.PistolShell"; } break; case TE_RIFLE_SHELL: { soundname = "Bounce.RifleShell"; } break; case TE_SHOTGUN_SHELL: { soundname = "Bounce.ShotgunShell"; } break; #endif } zvel = abs( pTemp->GetVelocity()[2] ); // only play one out of every n if ( isshellcasing ) { // play first bounce, then 1 out of 3 if ( zvel < 200 && random->RandomInt(0,3) ) return; } else { if ( random->RandomInt(0,5) ) return; } CSoundParameters params; if ( !C_BaseEntity::GetParametersForSound( soundname, params, NULL ) ) return; fvol = params.volume; if ( damp > 0.0 ) { int pitch; if ( isshellcasing ) { fvol *= MIN (1.0, ((float)zvel) / 350.0); } else { fvol *= MIN (1.0, ((float)zvel) / 450.0); } if ( !random->RandomInt(0,3) && !isshellcasing ) { pitch = random->RandomInt( params.pitchlow, params.pitchhigh ); } else { pitch = params.pitch; } CLocalPlayerFilter filter; EmitSound_t ep; ep.m_nChannel = params.channel; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nPitch = pitch; ep.m_pOrigin = &pTemp->GetAbsOrigin(); C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep ); } } //----------------------------------------------------------------------------- // Purpose: Add temp entity to visible entities list of it's in PVS // Input : *pEntity - // Output : int //----------------------------------------------------------------------------- int CTempEnts::AddVisibleTempEntity( C_LocalTempEntity *pEntity ) { int i; Vector mins, maxs; Vector model_mins, model_maxs; if ( !pEntity->GetModel() ) return 0; modelinfo->GetModelBounds( pEntity->GetModel(), model_mins, model_maxs ); for (i=0 ; i<3 ; i++) { mins[i] = pEntity->GetAbsOrigin()[i] + model_mins[i]; maxs[i] = pEntity->GetAbsOrigin()[i] + model_maxs[i]; } // FIXME: Vis isn't setup by the time we get here, so this call fails if // you try to add a tempent before the first frame is drawn, and it's // one frame behind the rest of the time. Fix this. // does the box intersect a visible leaf? //if ( engine->IsBoxInViewCluster( mins, maxs ) ) { // Temporary entities have no corresponding element in cl_entitylist pEntity->index = -1; // Add to list if( pEntity->m_RenderGroup == RENDER_GROUP_OTHER ) { pEntity->AddToLeafSystem(); } else { pEntity->AddToLeafSystem( pEntity->m_RenderGroup ); } return 1; } return 0; } //----------------------------------------------------------------------------- // Purpose: Runs Temp Ent simulation routines //----------------------------------------------------------------------------- void CTempEnts::Update(void) { VPROF_("CTempEnts::Update", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); static int gTempEntFrame = 0; float frametime; // Don't simulate while loading if ( ( m_TempEnts.Count() == 0 ) || !engine->IsInGame() ) { return; } // !!!BUGBUG -- This needs to be time based gTempEntFrame = (gTempEntFrame+1) & 31; frametime = gpGlobals->frametime; // in order to have tents collide with players, we have to run the player prediction code so // that the client has the player list. We run this code once when we detect any COLLIDEALL // tent, then set this BOOL to true so the code doesn't get run again if there's more than // one COLLIDEALL ent for this update. (often are). // !!! Don't simulate while paused.... This is sort of a hack, revisit. if ( frametime == 0 ) { FOR_EACH_LL( m_TempEnts, i ) { C_LocalTempEntity *current = m_TempEnts[ i ]; AddVisibleTempEntity( current ); } } else { int next = 0; for( int i = m_TempEnts.Head(); i != m_TempEnts.InvalidIndex(); i = next ) { next = m_TempEnts.Next( i ); C_LocalTempEntity *current = m_TempEnts[ i ]; // Kill it if ( !current->IsActive() || !current->Frame( frametime, gTempEntFrame ) ) { TempEntFree( i ); } else { // Cull to PVS (not frustum cull, just PVS) if ( !AddVisibleTempEntity( current ) ) { if ( !( current->flags & FTENT_PERSIST ) ) { // If we can't draw it this frame, just dump it. current->die = gpGlobals->curtime; // Don't fade out, just die current->flags &= ~FTENT_FADEOUT; TempEntFree( i ); } } } } } } // Recache tempents which might have been flushed void CTempEnts::LevelInit() { #ifndef TF_CLIENT_DLL m_pSpriteMuzzleFlash[0] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle1.vmt" ); m_pSpriteMuzzleFlash[1] = (model_t *)engine->LoadModel( "sprites/muzzleflash4.vmt" ); m_pSpriteMuzzleFlash[2] = (model_t *)engine->LoadModel( "sprites/muzzleflash4.vmt" ); m_pSpriteAR2Flash[0] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle1b.vmt" ); m_pSpriteAR2Flash[1] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle2b.vmt" ); m_pSpriteAR2Flash[2] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle3b.vmt" ); m_pSpriteAR2Flash[3] = (model_t *)engine->LoadModel( "sprites/ar2_muzzle4b.vmt" ); m_pSpriteCombineFlash[0] = (model_t *)engine->LoadModel( "effects/combinemuzzle1.vmt" ); m_pSpriteCombineFlash[1] = (model_t *)engine->LoadModel( "effects/combinemuzzle2.vmt" ); m_pShells[0] = (model_t *) engine->LoadModel( "models/weapons/shell.mdl" ); m_pShells[1] = (model_t *) engine->LoadModel( "models/weapons/rifleshell.mdl" ); m_pShells[2] = (model_t *) engine->LoadModel( "models/weapons/shotgun_shell.mdl" ); m_pShells[3] = (model_t *)engine->LoadModel( "models/weapons/MAGS/w_rif_ar2_small_mag.mdl") ; //m_Mag[3] = (model_t *)engine->LoadModel("models/weapons/unloaded/smg_mac10_mag.mdl"); m_Mag[5] = (model_t *)engine->LoadModel("models/weapons/MAGS/w_smg_ump45_mag.mdl"); m_Mag[4] = (model_t *)engine->LoadModel("models/weapons/MAGS/w_pist_p250_mag.mdl"); m_Mag[3] = (model_t *)engine->LoadModel("models/weapons/MAGS/w_mach_m249_mag.mdl"); #endif #if defined( HL1_CLIENT_DLL ) m_pHL1Shell = (model_t *)engine->LoadModel( "models/shell.mdl" ); m_pHL1ShotgunShell = (model_t *)engine->LoadModel( "models/shotgunshell.mdl" ); #endif #if defined( CSTRIKE_DLL ) || defined ( SDK_DLL ) m_pCS_9MMShell = (model_t *)engine->LoadModel( "models/Shells/shell_9mm.mdl" ); m_pCS_57Shell = (model_t *)engine->LoadModel( "models/Shells/shell_57.mdl" ); m_pCS_12GaugeShell = (model_t *)engine->LoadModel( "models/Shells/shell_12gauge.mdl" ); m_pCS_556Shell = (model_t *)engine->LoadModel( "models/Shells/shell_556.mdl" ); m_pCS_762NATOShell = (model_t *)engine->LoadModel( "models/Shells/shell_762nato.mdl" ); m_pCS_338MAGShell = (model_t *)engine->LoadModel( "models/Shells/shell_338mag.mdl" ); #endif } //----------------------------------------------------------------------------- // Purpose: Initialize TE system //----------------------------------------------------------------------------- void CTempEnts::Init (void) { m_pSpriteMuzzleFlash[0] = NULL; m_pSpriteMuzzleFlash[1] = NULL; m_pSpriteMuzzleFlash[2] = NULL; m_pSpriteAR2Flash[0] = NULL; m_pSpriteAR2Flash[1] = NULL; m_pSpriteAR2Flash[2] = NULL; m_pSpriteAR2Flash[3] = NULL; m_pSpriteCombineFlash[0] = NULL; m_pSpriteCombineFlash[1] = NULL; m_pShells[0] = NULL; m_pShells[1] = NULL; m_pShells[2] = NULL; m_pShells[3] = NULL; m_Mag[3] = NULL;//OverCharged m_Mag[4] = NULL;//OverCharged m_Mag[5] = NULL;//OverCharged #if defined( HL1_CLIENT_DLL ) m_pHL1Shell = NULL; m_pHL1ShotgunShell = NULL; #endif #if defined( CSTRIKE_DLL ) || defined ( SDK_DLL ) m_pCS_9MMShell = NULL; m_pCS_57Shell = NULL; m_pCS_12GaugeShell = NULL; m_pCS_556Shell = NULL; m_pCS_762NATOShell = NULL; m_pCS_338MAGShell = NULL; #endif // Clear out lists to start Clear(); } void CTempEnts::LevelShutdown() { // Free all active tempents. Clear(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTempEnts::Shutdown() { LevelShutdown(); } //----------------------------------------------------------------------------- // Purpose: Cache off all material references // Input : *pEmitter - Emitter used for material lookup //----------------------------------------------------------------------------- inline void CTempEnts::CacheMuzzleFlashes( void ) { m_Material_MuzzleFlash_Player[0] = ParticleMgr()->GetPMaterial("effects/muzzleflash1"); m_Material_MuzzleFlash_Player[1] = ParticleMgr()->GetPMaterial("effects/muzzleflash2"); m_Material_MuzzleFlash_Player[2] = ParticleMgr()->GetPMaterial("effects/muzzleflash3"); m_Material_MuzzleFlash_Player[3] = ParticleMgr()->GetPMaterial("effects/muzzleflash4"); m_Material_MuzzleFlash_NPC[0] = ParticleMgr()->GetPMaterial("effects/muzzleflash1"); m_Material_MuzzleFlash_NPC[1] = ParticleMgr()->GetPMaterial("effects/muzzleflash2"); m_Material_MuzzleFlash_NPC[2] = ParticleMgr()->GetPMaterial("effects/muzzleflash3"); m_Material_MuzzleFlash_NPC[3] = ParticleMgr()->GetPMaterial("effects/muzzleflash4"); m_Material_Combine_MuzzleFlash_Player[0] = ParticleMgr()->GetPMaterial("effects/combinemuzzle1_noz"); m_Material_Combine_MuzzleFlash_Player[1] = ParticleMgr()->GetPMaterial("effects/combinemuzzle2_noz"); m_Material_Combine_MuzzleFlash_NPC[0] = ParticleMgr()->GetPMaterial("effects/combinemuzzle1"); m_Material_Combine_MuzzleFlash_NPC[1] = ParticleMgr()->GetPMaterial("effects/combinemuzzle2"); } void CTempEnts::MuzzleFlash_SMG2_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { //////////////////////////////////////////////////////////////////////////////////////// мнбши лернд ///////////////////////////////////////////////////////////////////////////// VPROF_BUDGET("MuzzleFlash_SMG2_Player_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_SMG2_Player_Particle_Effect", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); Vector forward(7, 0, 0), right(0, 1.3, -1.3), offset; //NOTENOTE: All coords are in local space Vector forward0(30, 0, 0); pSimple->SetDrawBeforeViewModel(true); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); AngleVectors(angles, &forward, NULL, NULL); // if (cl_tracer_type.GetInt() == 2) // { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; // DispatchParticleEffect( "weapon_muzzle_flash_rifle_and_smg", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), "muzzle", false); DispatchParticleEffect("pd2_muzzle_normal_oicw", PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), "muzzle", false); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } void CTempEnts::MuzzleFlash_SMG2_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { //Draw the cloud of fire FX_MuzzleEffectAttached(1.0f, hEntity, attachmentIndex, NULL, true); } //----------------------------------------------------------------------------- // Purpose: // Input : entityIndex - // attachmentIndex - //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_Combine_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_Combine_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash", hEntity, attachmentIndex); CacheMuzzleFlashes(); SimpleParticle *pParticle; Vector forward(1, 0, 0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat(2.0f, 2.25f); //pSimple->SetDrawBeforeViewModel(true); // Flash for (int i = 1; i < 6; i++) { offset = (forward * (i*8.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_Combine_MuzzleFlash_Player[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.025f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (12 - (i)) / 12) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } // Tack on the smoke pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_Combine_MuzzleFlash_Player[random->RandomInt(0, 1)], vec3_origin); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.025f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = random->RandomInt(64, 128); pParticle->m_uchEndAlpha = 32; pParticle->m_uchStartSize = random->RandomFloat(10.0f, 16.0f); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; /*VPROF_BUDGET("MuzzleFlash_Combine_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); // If the material isn't available, let's not do anything. if (g_Mat_Combine_Muzzleflash[0] == NULL) { return; } CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash", hEntity, attachmentIndex); SimpleParticle *pParticle; Vector forward(1, 0, 0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat(1.0f, 1.5f); float burstSpeed = random->RandomFloat(50.0f, 150.0f); #define FRONT_LENGTH 6 // Front flash for (int i = 1; i < FRONT_LENGTH; i++) { offset = (forward * (i*2.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.1f; pParticle->m_vecVelocity = forward * burstSpeed; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255.0f; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (FRONT_LENGTH*1.25f - (i)) / (FRONT_LENGTH)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } Vector right(0, 1, 0), up(0, 0, 1); Vector dir = right - up; #define SIDE_LENGTH 6 burstSpeed = random->RandomFloat(50.0f, 150.0f); // Diagonal flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } dir = right + up; burstSpeed = random->RandomFloat(50.0f, 150.0f); // Diagonal flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (-dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * -burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } dir = up; burstSpeed = random->RandomFloat(50.0f, 150.0f); // Top flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[2], vec3_origin); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.3f, 0.4f); pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = flScale * random->RandomFloat(12.0f, 16.0f); pParticle->m_uchEndSize = 0.0f; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; matrix3x4_t matAttachment; Vector origin; // Grab the origin out of the transform for the attachment if (FX_GetAttachmentTransform(hEntity, attachmentIndex, matAttachment)) { origin.x = matAttachment[0][3]; origin.y = matAttachment[1][3]; origin.z = matAttachment[2][3]; } else { //NOTENOTE: If you're here, you've specified an entity or an attachment that is invalid Assert(0); return; }*/ } //----------------------------------------------------------------------------- // Purpose: // Input : &origin - // &angles - // entityIndex - //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_Combine_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_Combine_NPC", VPROF_BUDGETGROUP_PARTICLE_RENDERING); // If the material isn't available, let's not do anything. if (g_Mat_Combine_Muzzleflash[0] == NULL) { return; } CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_Combine_NPC", hEntity, attachmentIndex); SimpleParticle *pParticle; Vector forward(1, 0, 0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat(1.0f, 1.5f); float burstSpeed = random->RandomFloat(50.0f, 150.0f); #define FRONT_LENGTH 6 // Front flash for (int i = 1; i < FRONT_LENGTH; i++) { offset = (forward * (i*2.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.1f; pParticle->m_vecVelocity = forward * burstSpeed; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255.0f; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (FRONT_LENGTH*1.25f - (i)) / (FRONT_LENGTH)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } Vector right(0, 1, 0), up(0, 0, 1); Vector dir = right - up; #define SIDE_LENGTH 6 burstSpeed = random->RandomFloat(50.0f, 150.0f); // Diagonal flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } dir = right + up; burstSpeed = random->RandomFloat(50.0f, 150.0f); // Diagonal flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (-dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * -burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } dir = up; burstSpeed = random->RandomFloat(50.0f, 150.0f); // Top flash for (int i = 1; i < SIDE_LENGTH; i++) { offset = (dir * (i*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[random->RandomInt(0, 1)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.2f; pParticle->m_vecVelocity = dir * burstSpeed * 0.25f; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = ((random->RandomFloat(2.0f, 4.0f) * (SIDE_LENGTH - (i)) / (SIDE_LENGTH*0.5f)) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_Combine_Muzzleflash[2], vec3_origin); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.3f, 0.4f); pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = flScale * random->RandomFloat(12.0f, 16.0f); pParticle->m_uchEndSize = 0.0f; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; matrix3x4_t matAttachment; Vector origin; // Grab the origin out of the transform for the attachment if (FX_GetAttachmentTransform(hEntity, attachmentIndex, matAttachment)) { origin.x = matAttachment[0][3]; origin.y = matAttachment[1][3]; origin.z = matAttachment[2][3]; } else { //NOTENOTE: If you're here, you've specified an entity or an attachment that is invalid Assert(0); return; } } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_AR2_NPC(const Vector &origin, const QAngle &angles, ClientEntityHandle_t hEntity) { //Draw the cloud of fire FX_MuzzleEffect(origin, angles, 1.0f, hEntity); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_SMG1_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { //Draw the cloud of fire FX_MuzzleEffectAttached(1.0f, hEntity, attachmentIndex, NULL, true); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_SMG1_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_SMG1_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_SMG1_Player", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); SimpleParticle *pParticle; Vector forward(1, 0, 0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat(1.25f, 1.5f); pSimple->SetDrawBeforeViewModel(true); // Flash for (int i = 1; i < 6; i++) { offset = (forward * (i*8.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.025f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (8 - (i)) / 6) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_AK47_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { //Draw the cloud of fire FX_MuzzleEffectAttached(1.0f, hEntity, attachmentIndex, NULL, true); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTempEnts::MuzzleFlash_AK47_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_AK47_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_AK47_Player", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); SimpleParticle *pParticle; Vector forward(1, 0, 0), offset; //NOTENOTE: All coords are in local space float flScale = random->RandomFloat(1.25f, 1.5f); pSimple->SetDrawBeforeViewModel(true); // Flash for (int i = 1; i < 6; i++) { offset = (forward * (i*8.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.025f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (8 - (i)) / 6) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_Shotgun_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_Shotgun_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CSimpleEmitter::Create("MuzzleFlash_Shotgun_Player"); pSimple->SetDrawBeforeViewModel(true); CacheMuzzleFlashes(); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); Vector forward; AngleVectors(angles, &forward, NULL, NULL); SimpleParticle *pParticle; Vector offset; // Smoke offset = origin + forward * 8.0f; pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[0], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.5f, 1.0f); pParticle->m_vecVelocity.Init(); pParticle->m_vecVelocity = forward * random->RandomFloat(8.0f, 64.0f); pParticle->m_vecVelocity[2] += random->RandomFloat(4.0f, 16.0f); int color = random->RandomInt(200, 255); pParticle->m_uchColor[0] = color; pParticle->m_uchColor[1] = color; pParticle->m_uchColor[2] = color; pParticle->m_uchStartAlpha = random->RandomInt(64, 128); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = random->RandomInt(2, 4); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 8.0f; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = random->RandomFloat(-0.5f, 0.5f); float flScale = random->RandomFloat(1.25f, 1.5f); // Flash for (int i = 1; i < 6; i++) { offset = origin + (forward * (i*8.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.01f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (8 - (i)) / 6) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } // // Trails // /*CSmartPtr pTrails = CTrailParticles::Create("MuzzleFlash_Shotgun_Player"); pTrails->SetSortOrigin(origin); TrailParticle *pTrailParticle; pTrails->SetFlag(bitsPARTICLE_TRAIL_FADE); pTrails->m_ParticleCollision.SetGravity(0.0f); int numEmbers = random->RandomInt(4, 8); for (int i = 0; i < numEmbers; i++) { pTrailParticle = (TrailParticle *)pTrails->AddParticle(sizeof(TrailParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], origin); if (pTrailParticle == NULL) return; pTrailParticle->m_flLifetime = 0.0f; pTrailParticle->m_flDieTime = random->RandomFloat(0.1f, 0.2f); float spread = 0.05f; pTrailParticle->m_vecVelocity.Random(-spread, spread); pTrailParticle->m_vecVelocity += forward; VectorNormalize(pTrailParticle->m_vecVelocity); VectorNormalize(forward); float dot = forward.Dot(pTrailParticle->m_vecVelocity); dot = (1.0f - fabs(dot)) / spread; pTrailParticle->m_vecVelocity *= (random->RandomFloat(256.0f, 1024.0f) * (1.0f - dot)); Color32Init(pTrailParticle->m_color, 255, 242, 191, 255); pTrailParticle->m_flLength = 0.05f; pTrailParticle->m_flWidth = random->RandomFloat(0.25f, 0.5f); }*/ } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_Shotgun_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { //Draw the cloud of fire FX_MuzzleEffectAttached(0.75f, hEntity, attachmentIndex); // If the material isn't available, let's not do anything else. if (g_Mat_SMG_Muzzleflash[0] == NULL) { return; } QAngle angles; Vector forward; int i; // Setup the origin. Vector origin; IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle(hEntity); if (!pRenderable) return; pRenderable->GetAttachment(attachmentIndex, origin, angles); AngleVectors(angles, &forward); //Embers less often if (random->RandomInt(0, 2) == 0) { //Embers CSmartPtr pEmbers = CEmberEffect::Create("muzzle_embers"); pEmbers->SetSortOrigin(origin); SimpleParticle *pParticle; int numEmbers = random->RandomInt(0, 4); for (int i = 0; i < numEmbers; i++) { pParticle = (SimpleParticle *)pEmbers->AddParticle(sizeof(SimpleParticle), g_Mat_SMG_Muzzleflash[0], origin); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.2f, 0.4f); pParticle->m_vecVelocity.Random(-0.05f, 0.05f); pParticle->m_vecVelocity += forward; VectorNormalize(pParticle->m_vecVelocity); pParticle->m_vecVelocity *= random->RandomFloat(64.0f, 256.0f); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 128; pParticle->m_uchColor[2] = 64; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = 0; pParticle->m_flRoll = 0; pParticle->m_flRollDelta = 0; } } // // Trails // CSmartPtr pTrails = CTrailParticles::Create("MuzzleFlash_Shotgun_NPC"); pTrails->SetSortOrigin(origin); TrailParticle *pTrailParticle; pTrails->SetFlag(bitsPARTICLE_TRAIL_FADE); pTrails->m_ParticleCollision.SetGravity(0.0f); int numEmbers = random->RandomInt(4, 8); for (i = 0; i < numEmbers; i++) { pTrailParticle = (TrailParticle *)pTrails->AddParticle(sizeof(TrailParticle), g_Mat_SMG_Muzzleflash[0], origin); if (pTrailParticle == NULL) return; pTrailParticle->m_flLifetime = 0.0f; pTrailParticle->m_flDieTime = random->RandomFloat(0.1f, 0.2f); float spread = 0.05f; pTrailParticle->m_vecVelocity.Random(-spread, spread); pTrailParticle->m_vecVelocity += forward; VectorNormalize(pTrailParticle->m_vecVelocity); VectorNormalize(forward); float dot = forward.Dot(pTrailParticle->m_vecVelocity); dot = (1.0f - fabs(dot)) / spread; pTrailParticle->m_vecVelocity *= (random->RandomFloat(256.0f, 1024.0f) * (1.0f - dot)); Color32Init(pTrailParticle->m_color, 255, 242, 191, 255); pTrailParticle->m_flLength = 0.05f; pTrailParticle->m_flWidth = random->RandomFloat(0.25f, 0.5f); } } //================================================== // Purpose: //================================================== void CTempEnts::MuzzleFlash_357_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_357_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CSimpleEmitter::Create("MuzzleFlash_357_Player"); pSimple->SetDrawBeforeViewModel(true); CacheMuzzleFlashes(); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); Vector forward; AngleVectors(angles, &forward, NULL, NULL); SimpleParticle *pParticle; Vector offset; // Smoke offset = origin + forward * 8.0f; pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[0], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.5f, 1.0f); pParticle->m_vecVelocity.Init(); pParticle->m_vecVelocity = forward * random->RandomFloat(8.0f, 64.0f); pParticle->m_vecVelocity[2] += random->RandomFloat(4.0f, 16.0f); int color = random->RandomInt(200, 255); pParticle->m_uchColor[0] = color; pParticle->m_uchColor[1] = color; pParticle->m_uchColor[2] = color; pParticle->m_uchStartAlpha = random->RandomInt(64, 128); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = random->RandomInt(2, 4); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 8.0f; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = random->RandomFloat(-0.5f, 0.5f); float flScale = random->RandomFloat(1.25f, 1.5f); // Flash for (int i = 1; i < 6; i++) { offset = origin + (forward * (i*8.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.01f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (8 - (i)) / 6) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_Pistol_Player(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_Pistol_Player", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CSimpleEmitter::Create("MuzzleFlash_Pistol_Player"); pSimple->SetDrawBeforeViewModel(true); CacheMuzzleFlashes(); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); Vector forward; AngleVectors(angles, &forward, NULL, NULL); SimpleParticle *pParticle; Vector offset; // Smoke offset = origin + forward * 8.0f; if (random->RandomInt(0, 3) != 0) { pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), g_Mat_DustPuff[0], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat(0.25f, 0.5f); pParticle->m_vecVelocity.Init(); pParticle->m_vecVelocity = forward * random->RandomFloat(48.0f, 64.0f); pParticle->m_vecVelocity[2] += random->RandomFloat(4.0f, 16.0f); int color = random->RandomInt(200, 255); pParticle->m_uchColor[0] = color; pParticle->m_uchColor[1] = color; pParticle->m_uchColor[2] = color; pParticle->m_uchStartAlpha = random->RandomInt(64, 128); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = random->RandomInt(2, 4); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4.0f; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = random->RandomFloat(-0.1f, 0.1f); } float flScale = random->RandomFloat(1.0f, 1.25f); // Flash for (int i = 1; i < 6; i++) { offset = origin + (forward * (i*4.0f*flScale)); pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), m_Material_MuzzleFlash_Player[random->RandomInt(0, 3)], offset); if (pParticle == NULL) return; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 0.01f; pParticle->m_vecVelocity.Init(); pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 200 + random->RandomInt(0, 55); pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; pParticle->m_uchStartSize = ((random->RandomFloat(6.0f, 8.0f) * (8 - (i)) / 6) * flScale); pParticle->m_uchEndSize = pParticle->m_uchStartSize; pParticle->m_flRoll = random->RandomInt(0, 360); pParticle->m_flRollDelta = 0.0f; } } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_Pistol_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { FX_MuzzleEffectAttached(0.5f, hEntity, attachmentIndex, NULL, true); } //================================================== // Purpose: // Input: //================================================== void CTempEnts::MuzzleFlash_RPG_NPC(ClientEntityHandle_t hEntity, int attachmentIndex) { //Draw the cloud of fire FX_MuzzleEffectAttached(1.5f, hEntity, attachmentIndex); } void CTempEnts::RocketFlare( const Vector& pos ) { C_LocalTempEntity *pTemp; const model_t *model; int nframeCount; model = (model_t *)engine->LoadModel( "sprites/animglow01.vmt" ); if ( !model ) { return; } nframeCount = modelinfo->GetModelFrameCount( model ); pTemp = TempEntAlloc( pos, model ); if ( !pTemp ) return; pTemp->m_flFrameMax = nframeCount - 1; pTemp->SetRenderMode( kRenderGlow ); pTemp->m_nRenderFX = kRenderFxNoDissipation; pTemp->tempent_renderamt = 255; pTemp->m_flFrameRate = 1.0; pTemp->m_flFrame = random->RandomInt( 0, nframeCount - 1); pTemp->m_flSpriteScale = 1.0; pTemp->SetAbsOrigin( pos ); pTemp->die = gpGlobals->curtime + 0.01; } void CTempEnts::HL1EjectBrass( const Vector &vecPosition, const QAngle &angAngles, const Vector &vecVelocity, int nType ) { const model_t *pModel = NULL; #if defined( HL1_CLIENT_DLL ) switch ( nType ) { case 0: default: pModel = m_pHL1Shell; break; case 1: pModel = m_pHL1ShotgunShell; break; } #endif if ( pModel == NULL ) return; C_LocalTempEntity *pTemp = TempEntAlloc( vecPosition, pModel ); if ( pTemp == NULL ) return; switch ( nType ) { case 0: default: pTemp->hitSound = BOUNCE_SHELL; break; case 1: pTemp->hitSound = BOUNCE_SHOTSHELL; break; } pTemp->m_nBody = 0; pTemp->flags |= ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE ); pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat( -512,511 ); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat( -256,255 ); pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat( -256,255 ); //Face forward pTemp->SetAbsAngles( angAngles ); pTemp->SetRenderMode( kRenderNormal ); pTemp->tempent_renderamt = 255; // Set this for fadeout pTemp->SetVelocity( vecVelocity ); pTemp->die = gpGlobals->curtime + 2.5; } #define SHELLTYPE_PISTOL 0 #define SHELLTYPE_RIFLE 1 #define SHELLTYPE_SHOTGUN 2 void CTempEnts::CSEjectBrass( const Vector &vecPosition, const QAngle &angVelocity, int nVelocity, int shellType, CBasePlayer *pShooter ) { const model_t *pModel = NULL; int hitsound = TE_BOUNCE_SHELL; #if defined ( CSTRIKE_DLL ) || defined ( SDK_DLL ) switch( shellType ) { default: case CS_SHELL_9MM: hitsound = TE_PISTOL_SHELL; pModel = m_pCS_9MMShell; break; case CS_SHELL_57: hitsound = TE_PISTOL_SHELL; pModel = m_pCS_57Shell; break; case CS_SHELL_12GAUGE: hitsound = TE_SHOTGUN_SHELL; pModel = m_pCS_12GaugeShell; break; case CS_SHELL_556: hitsound = TE_RIFLE_SHELL; pModel = m_pCS_556Shell; break; case CS_SHELL_762NATO: hitsound = TE_RIFLE_SHELL; pModel = m_pCS_762NATOShell; break; case CS_SHELL_338MAG: hitsound = TE_RIFLE_SHELL; pModel = m_pCS_338MAGShell; break; } #endif if ( pModel == NULL ) return; Vector forward, right, up; Vector velocity; Vector origin; QAngle angle; // Add some randomness to the velocity AngleVectors( angVelocity, &forward, &right, &up ); velocity = forward * nVelocity * random->RandomFloat( 1.2, 2.8 ) + up * random->RandomFloat( -10, 10 ) + right * random->RandomFloat( -20, 20 ); if( pShooter ) velocity += pShooter->GetAbsVelocity(); C_LocalTempEntity *pTemp = TempEntAlloc( vecPosition, pModel ); if ( !pTemp ) return; if( pShooter ) pTemp->SetAbsAngles( pShooter->EyeAngles() ); else pTemp->SetAbsAngles( vec3_angle ); pTemp->SetVelocity( velocity ); pTemp->hitSound = hitsound; pTemp->SetGravity( 0.4 ); pTemp->m_nBody = 0; pTemp->flags = FTENT_FADEOUT | FTENT_GRAVITY | FTENT_COLLIDEALL | FTENT_HITSOUND | FTENT_ROTATE | FTENT_CHANGERENDERONCOLLIDE; pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-256,256); pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-256,256); pTemp->m_vecTempEntAngVelocity[2] = 0; pTemp->SetRenderMode( kRenderNormal ); pTemp->tempent_renderamt = 255; pTemp->die = gpGlobals->curtime + 10; bool bViewModelBrass = false; if ( pShooter && pShooter->GetObserverMode() == OBS_MODE_IN_EYE ) { // we are spectating the shooter in first person view pShooter = ToBasePlayer( pShooter->GetObserverTarget() ); bViewModelBrass = true; } if ( pShooter ) { pTemp->clientIndex = pShooter->entindex(); bViewModelBrass |= pShooter->IsLocalPlayer(); } else { pTemp->clientIndex = 0; } if ( bViewModelBrass ) { // for viewmodel brass put it in the viewmodel renderer group pTemp->m_RenderGroup = RENDER_GROUP_VIEW_MODEL_OPAQUE; } } static ConVar oc_test_muzzle_sphere_x("oc_test_muzzle_sphere_x", "1", FCVAR_ARCHIVE); static ConVar oc_test_muzzle_sphere_y("oc_test_muzzle_sphere_y", "1", FCVAR_ARCHIVE); static ConVar oc_test_muzzle_sphere_z("oc_test_muzzle_sphere_z", "1", FCVAR_ARCHIVE); void CTempEnts::MuzzleFlash_General_Player_Particle_Effect(const char *name, int colR, int colG, int colB, ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_General_Player_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_General_Player_Particle_Effect", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); if (name == NULL || (name && (!V_strlen(name) || FStrEq(name, "None") || FStrEq(name, "none")))) return; Vector forward(7, 0, 0), right(0, 1.3, -1.3), offset; //NOTENOTE: All coords are in local space Vector forward0(30, 0, 0), light; pSimple->SetDrawBeforeViewModel(true); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); AngleVectors(angles, &forward, NULL, NULL); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; C_BaseEntity *pVM = pPlayer->GetViewModel(); if (!pVM) return; if (cvar->FindVar("oc_state_InSecondFire")->GetInt() == 1) { Vector vForward, vRight, vUp, vThrowPos, vThrowVel; QAngle pAngles; pPlayer->EyeVectors(&vForward, &vRight, &vUp); pAngles = pPlayer->EyeAngles(); vThrowPos = pPlayer->EyePosition(); vThrowPos += vForward * oc_InScope_weapon_muzzleflash_position_x.GetFloat(); vThrowPos += vRight * oc_InScope_weapon_muzzleflash_position_y.GetFloat(); vThrowPos += vUp * oc_InScope_weapon_muzzleflash_position_z.GetFloat(); DispatchParticleEffect(name, vThrowPos, pAngles, pVM); /*if (pPlayer->GetWaterLevel() != 3) { DispatchParticleEffect(name, vThrowPos, pAngles, pPlayer->GetViewModel()); } else { const char *nameUW = pWeapon->GetWpnData().iMuzzleFlashUnderWaterType; if (nameUW == NULL || (nameUW && (!V_strlen(nameUW) || V_strcmp(nameUW, "None") || V_strcmp(nameUW, "none")))) return; Msg("Error: %s does't have underwater particle definition in script fire \n", pWeapon->GetClassname()); DispatchParticleEffect(nameUW, vThrowPos, pAngles, pPlayer->GetViewModel()); }*/ } if (cvar->FindVar("oc_state_InSecondFire")->GetInt() == 0) { int iAttachment = attachmentIndex; if (pWeapon->iMuzzle == 2) { char nameMF[64]; Q_snprintf(nameMF, sizeof(nameMF), "%s", pWeapon->GetWpnData().iAttachment_second); const char *nameP = nameMF; if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) iAttachment = pWeapon->LookupAttachment(nameP);//muzzle1 else iAttachment = pVM->LookupAttachment(nameP); } if (pWeapon->m_bSilenced) { char nameMF[64]; Q_snprintf(nameMF, sizeof(nameMF), "%s", pWeapon->GetWpnData().iAttachment_sil); const char *nameP = nameMF; if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt()) iAttachment = pWeapon->LookupAttachment(nameP);//muzzle_sil else iAttachment = pVM->LookupAttachment(nameP); } DispatchParticleEffect(name, PATTACH_POINT_FOLLOW, pVM, iAttachment, false); } } void CTempEnts::MuzzleFlash_General_NPC_Particle_Effect(const char *name, int colR, int colG, int colB, ClientEntityHandle_t hEntity, int attachmentIndex) { if (name == NULL || (name && (!V_strlen(name) || FStrEq(name, "None") || FStrEq(name, "none")))) return; QAngle angles; Vector forward; // Setup the origin. Vector origin; IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle(hEntity); if (!pRenderable) return; //pRenderable->GetAttachment(attachmentIndex, origin, angles); //AngleVectors(angles, &forward); //CBaseCombatWeapon *pEnt = ClientEntityList().GetBaseEntityFromHandle(hEntity); C_BaseCombatWeapon *pWeapon = static_cast(ClientEntityList().GetBaseEntityFromHandle(hEntity)); if (!pWeapon) return; DispatchParticleEffect(name, PATTACH_POINT_FOLLOW, pWeapon, attachmentIndex, false); //DispatchParticleEffect(name, PATTACH_POINT_FOLLOW, pEnt, "muzzle", false); } void CTempEnts::MuzzleFlash_General_Player_Secondary_Particle_Effect(const char *name, int colR, int colG, int colB, ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_General_Player_Secondary_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("MuzzleFlash_General_Player_Particle_Effect", hEntity, attachmentIndex, FLE_VIEWMODEL); CacheMuzzleFlashes(); if (name == NULL || (name && (!V_strlen(name) || FStrEq(name, "None") || FStrEq(name, "none")))) return; Vector forward(7, 0, 0), right(0, 1.3, -1.3), offset; Vector forward0(30, 0, 0), light; pSimple->SetDrawBeforeViewModel(true); Vector origin; QAngle angles; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); AngleVectors(angles, &forward, NULL, NULL); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (!pPlayer) return; C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; C_BaseEntity *pVM = pPlayer->GetViewModel(); if (!pVM) return; if (cvar->FindVar("oc_state_InSecondFire")->GetInt() == 1) { Vector vForward, vRight, vUp, vThrowPos, vThrowVel; QAngle pAngles; pPlayer->EyeVectors(&vForward, &vRight, &vUp); pAngles = pPlayer->EyeAngles(); vThrowPos = pPlayer->EyePosition(); vThrowPos += vForward * oc_InScope_weapon_muzzleflash_position_x.GetFloat(); vThrowPos += vRight * oc_InScope_weapon_muzzleflash_position_y.GetFloat(); vThrowPos += vUp * oc_InScope_weapon_muzzleflash_position_z.GetFloat(); DispatchParticleEffect(name, vThrowPos, pAngles, pVM); } if (cvar->FindVar("oc_state_InSecondFire")->GetInt() == 0) { DispatchParticleEffect(name, PATTACH_POINT_FOLLOW, pVM, attachmentIndex, false); } } void CTempEnts::MuzzleFlash_General_NPC_Secondary_Particle_Effect(const char *name, int colR, int colG, int colB, ClientEntityHandle_t hEntity, int attachmentIndex) { if (name == NULL || (name && (!V_strlen(name) || FStrEq(name, "None") || FStrEq(name, "none")))) return; QAngle angles; Vector forward; // Setup the origin. Vector origin; IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle(hEntity); if (!pRenderable) return; //pRenderable->GetAttachment(attachmentIndex, origin, angles); //AngleVectors(angles, &forward); C_BaseCombatWeapon *pWeapon = static_cast(ClientEntityList().GetBaseEntityFromHandle(hEntity)); //C_BaseEntity *pWeapon = ClientEntityList().GetBaseEntityFromHandle(hEntity); if (!pWeapon) return; DispatchParticleEffect(name, PATTACH_POINT_FOLLOW, pWeapon, attachmentIndex, false); } void CTempEnts::MuzzleFlash_Combine_NPC_Particle_Effect(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_Combine_NPC_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); // If the material isn't available, let's not do anything. /*if (g_Mat_Combine_Muzzleflash[0] == NULL) { return; } */ QAngle angles; Vector forward; // Setup the origin. Vector origin; /*IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle(hEntity); if (!pRenderable) return; pRenderable->GetAttachment(attachmentIndex, origin, angles);*/ /*AngleVectors(angles, &forward); DispatchParticleEffect("ar2_normal_npc", origin, angles); DispatchParticleEffect("muzzle_sparks_ar2_npc", origin, angles); DispatchParticleEffect("muzzle_sparks_ar2_360_npc", origin, angles);*/ // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); C_BaseCombatCharacter *pOwner = ToBaseCombatCharacter(ClientEntityList().GetBaseEntity(hEntity.GetEntryIndex()));//GetOwnerEntity() if (pOwner) DispatchParticleEffect("ar2_normal_npc", PATTACH_POINT_FOLLOW, pOwner, attachmentIndex, true); } void CTempEnts::MuzzleFlash_AirboatGun_NPC_Particle_Effect(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_AirboatGun_NPC_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); QAngle angles; Vector forward; // Setup the origin. Vector origin; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); C_BaseAnimating *pVehicleAnimating = dynamic_cast(ClientEntityList().GetBaseEntity(hEntity.GetEntryIndex())); //C_BaseAnimating *pOwner = ToBaseCombatCharacter(ClientEntityList().GetBaseEntity(hEntity.GetEntryIndex()));//GetOwnerEntity() if (pVehicleAnimating) DispatchParticleEffect("abgun_normal2", PATTACH_POINT_FOLLOW, pVehicleAnimating, 1, false); } void CTempEnts::MuzzleFlash_APC_NPC_Particle_Effect(ClientEntityHandle_t hEntity, int attachmentIndex) { VPROF_BUDGET("MuzzleFlash_AirboatGun_NPC_Particle_Effect", VPROF_BUDGETGROUP_PARTICLE_RENDERING); QAngle angles; Vector forward; // Setup the origin. Vector origin; // Get our attachment's transformation matrix FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); C_BaseAnimating *pVehicleAnimating = dynamic_cast(ClientEntityList().GetBaseEntity(hEntity.GetEntryIndex())); //C_BaseAnimating *pOwner = ToBaseCombatCharacter(ClientEntityList().GetBaseEntity(hEntity.GetEntryIndex()));//GetOwnerEntity() if (pVehicleAnimating) DispatchParticleEffect("abgun_normal2", PATTACH_POINT_FOLLOW, pVehicleAnimating, attachmentIndex, false); } //////////////////////////////////////////////////////////////////////OverCharged/////////////////////////////////////////////////////////////////////////////////// void CTempEnts::Shell_exhaust(C_BasePlayer *pPlayer) { if (!pPlayer) return; C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; const char *nameP = pWeapon->GetWpnData().iWeaponShellExhaustParticle; if (nameP == NULL || (nameP && (!V_strlen(nameP) || FStrEq(nameP, "None") || FStrEq(nameP, "none")))) { Msg("Error: %s does't have shell exhaust particle definition in script fire \n", pWeapon->GetClassname()); return; } int iAttachment = 0; if (pWeapon->iMuzzle == 2) { iAttachment = pPlayer->GetViewModel()->LookupAttachment(pWeapon->GetWpnData().iWeaponShellExhaustAttachmentDual2);//4 } else { iAttachment = pPlayer->GetViewModel()->LookupAttachment(pWeapon->GetWpnData().iWeaponShellExhaustAttachment);//3 } DispatchParticleEffect(nameP, PATTACH_POINT_FOLLOW, pPlayer->GetViewModel(), iAttachment, false); } void CTempEnts::Shell_exhaust(C_BaseCombatWeapon *pWeapon) { if (!pWeapon) return; const char *nameP = pWeapon->GetWpnData().iWeaponShellExhaustParticle; if (nameP == NULL || (nameP && (!V_strlen(nameP) || FStrEq(nameP, "None") || FStrEq(nameP, "none")))) { Msg("Error: %s does't have shell exhaust particle definition in script fire \n", pWeapon->GetClassname()); return; } int iAttachment = 0; if (pWeapon->iMuzzle == 2) { iAttachment = pWeapon->LookupAttachment(pWeapon->GetWpnData().iWeaponShellExhaustAttachmentDual2); } else { iAttachment = pWeapon->LookupAttachment(pWeapon->GetWpnData().iWeaponShellExhaustAttachment); } DispatchParticleEffect(nameP, PATTACH_POINT_FOLLOW, pWeapon, iAttachment, false); } void CTempEnts::Shell_exhaust_Npc(C_BaseCombatCharacter *pOwner) { if (!pOwner) return; C_BaseCombatWeapon *pWeapon = pOwner->GetActiveWeapon(); if (!pWeapon) return; const char *nameP = pWeapon->GetWpnData().iWeaponShellExhaustParticle; if (nameP == NULL || (nameP && (!V_strlen(nameP) || FStrEq(nameP, "None") || FStrEq(nameP, "none")))) { Msg("Error: %s does't have shell exhaust particle definition in script fire \n", pWeapon->GetClassname()); return; } int iAttachment = pWeapon->LookupAttachment(pWeapon->GetWpnData().iWeaponShellExhaustAttachment); DispatchParticleEffect(nameP, PATTACH_POINT_FOLLOW, pWeapon, iAttachment, false); } void CTempEnts::TracerCallBack(ClientEntityHandle_t hEntity, int attachmentIndex, const trace_t &tr, int trType) { VPROF_BUDGET("TracerCallBack", VPROF_BUDGETGROUP_PARTICLE_RENDERING); CSmartPtr pSimple = CLocalSpaceEmitter::Create("TracerCallBack", hEntity, attachmentIndex); CacheMuzzleFlashes(); Vector origin; pSimple->SetDrawBeforeViewModel(false); QAngle angles; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer == NULL) return; C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); if (!pWeapon) return; int indexT = random->RandomInt(0, pWeapon->GetWpnData().externalIndexT); char nameT2[256]; const char *nameT; Q_snprintf(nameT2, sizeof(nameT2), "%s", pWeapon->GetWpnData().iMuzzleTracerType[indexT]); nameT = nameT2; if (nameT2 == NULL || (nameT2 && (!V_strlen(nameT2) || FStrEq(nameT2, "None") || FStrEq(nameT2, "none")))) { Msg("Error: %s does't have tracer particle definition in script fire \n", pWeapon->GetClassname()); return; } FX_GetAttachmentTransform(hEntity, attachmentIndex, &origin, &angles); pSimple->GetBinding().SetBBox(origin - Vector(4, 4, 4), origin + Vector(4, 4, 4)); CTraceFilterSkipPlayerAndViewModel traceFilter; //int iMask = MASK_ALL;//MASK_OPAQUE_AND_NPCS //iMask &= ~CONTENTS_HITBOX; //iMask |= CONTENTS_WINDOW; trace_t tr2; Vector Forward, Up, Right; pPlayer->EyeVectors(&Forward, &Right, &Up); if (cvar->FindVar("oc_adjust_weapon_tracers_offset")->GetInt() == 1) { origin += Forward * cvar->FindVar("oc_adjust_weapon_tracers_offset_x")->GetFloat(); origin += Right * cvar->FindVar("oc_adjust_weapon_tracers_offset_y")->GetFloat(); origin += Up * cvar->FindVar("oc_adjust_weapon_tracers_offset_z")->GetFloat(); } else { if (pWeapon->IsScopeSighted() && !pWeapon->IsIronSighted()) { if (oc_particle_tracers.GetInt()) { origin += Forward * pWeapon->GetWpnData().ScopeParticleTracerPosition.x; origin += Right * pWeapon->GetWpnData().ScopeParticleTracerPosition.y; origin += Up * pWeapon->GetWpnData().ScopeParticleTracerPosition.z; } else { origin += Forward * pWeapon->GetWpnData().ScopeOriginTracerPosition.x; origin += Right * pWeapon->GetWpnData().ScopeOriginTracerPosition.y; origin += Up * pWeapon->GetWpnData().ScopeOriginTracerPosition.z; } } else if (pWeapon->IsIronSighted() && !pWeapon->IsScopeSighted()) { if (oc_particle_tracers.GetInt()) { origin += Forward * pWeapon->GetWpnData().IrSightParticleTracerPosition.x; origin += Right * pWeapon->GetWpnData().IrSightParticleTracerPosition.y; origin += Up * pWeapon->GetWpnData().IrSightParticleTracerPosition.z; } else { origin += Forward * pWeapon->GetWpnData().IrSightOriginTracerPosition.x; origin += Right * pWeapon->GetWpnData().IrSightOriginTracerPosition.y; origin += Up * pWeapon->GetWpnData().IrSightOriginTracerPosition.z; } } else { if (oc_particle_tracers.GetInt()) { origin += Forward * pWeapon->GetWpnData().ParticleTracerPosition.x; origin += Right * pWeapon->GetWpnData().ParticleTracerPosition.y; origin += Up * pWeapon->GetWpnData().ParticleTracerPosition.z; } else { origin += Forward * pWeapon->GetWpnData().OriginTracerPosition.x; origin += Right * pWeapon->GetWpnData().OriginTracerPosition.y; origin += Up * pWeapon->GetWpnData().OriginTracerPosition.z; } } } UTIL_TraceLine(pPlayer->EyePosition(), tr.endpos, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr2); //UTIL_ParticleTracer(nameT, origin, tr.endpos, pPlayer->GetViewModel()->entindex(), attachmentIndex, trType);//OverCharged //DispatchParticleEffect(nameT, origin /*vFirePos*/, tr.endpos, vec3_angle, pPlayer->GetViewModel()); if (pWeapon->GetWpnData().TracersCombined) { UTIL_ParticleTracer(nameT, origin, tr.endpos, pPlayer->entindex(), attachmentIndex, trType); UTIL_Tracer(origin, tr.endpos, pPlayer->entindex(), TRACER_DONT_USE_ATTACHMENT, 6500, false, "CommonTracer"); } else { if (oc_particle_tracers.GetInt()) UTIL_ParticleTracer(nameT, origin, tr.endpos, pPlayer->entindex(), attachmentIndex, trType); else UTIL_Tracer(origin, tr.endpos, pPlayer->entindex(), TRACER_DONT_USE_ATTACHMENT, 6500, false, "CommonTracer"); } } void CTempEnts::MuzzleLightCallBack() { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer && pPlayer->GetActiveWeapon()) { if (pPlayer->GetActiveWeapon()->MuzzleFlashTypeIndex() >= 0 && pPlayer->GetWaterLevel() != 3) { pPlayer->GetActiveWeapon()->IsMuzzleFlashActive = true; pPlayer->GetActiveWeapon()->IsMuzzleFlashComplete = false; } } }