summaryrefslogtreecommitdiff
path: root/game/shared/dod/weapon_mg42.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/dod/weapon_mg42.cpp')
-rw-r--r--game/shared/dod/weapon_mg42.cpp843
1 files changed, 843 insertions, 0 deletions
diff --git a/game/shared/dod/weapon_mg42.cpp b/game/shared/dod/weapon_mg42.cpp
new file mode 100644
index 0000000..7321476
--- /dev/null
+++ b/game/shared/dod/weapon_mg42.cpp
@@ -0,0 +1,843 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "weapon_mg42.h"
+#include "engine/ivdebugoverlay.h"
+
+#if defined( CLIENT_DLL )
+
+ #include "tier1/KeyValues.h"
+ #include "particles_simple.h"
+ #include "particles_localspace.h"
+ #include "fx.h"
+ #include "c_dod_player.h"
+
+#else
+
+ #include "dod_player.h"
+
+#endif
+
+
+#ifdef CLIENT_DLL
+void ToolFramework_PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg );
+#endif
+
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponMG42, DT_WeaponMG42 )
+
+#ifdef GAME_DLL
+
+BEGIN_DATADESC( CWeaponMG42 )
+ DEFINE_THINKFUNC( CoolThink ),
+END_DATADESC()
+
+#endif
+
+BEGIN_NETWORK_TABLE( CWeaponMG42, DT_WeaponMG42 )
+#ifdef CLIENT_DLL
+ RecvPropInt ( RECVINFO( m_iWeaponHeat ) ),
+ RecvPropTime ( RECVINFO( m_flNextCoolTime ) ),
+ RecvPropBool ( RECVINFO( m_bOverheated ) ),
+#else
+ SendPropInt ( SENDINFO( m_iWeaponHeat ), 7, SPROP_UNSIGNED ),
+ SendPropFloat ( SENDINFO( m_flNextCoolTime ) ),
+ SendPropBool ( SENDINFO( m_bOverheated ) ),
+#endif
+END_NETWORK_TABLE()
+
+#ifdef CLIENT_DLL
+BEGIN_PREDICTION_DATA( CWeaponMG42 )
+ DEFINE_PRED_FIELD( m_iWeaponHeat, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD_TOL( m_flNextCoolTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ),
+ DEFINE_PRED_FIELD( m_bOverheated, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+END_PREDICTION_DATA()
+#endif
+
+LINK_ENTITY_TO_CLASS( weapon_mg42, CWeaponMG42 );
+PRECACHE_WEAPON_REGISTER( weapon_mg42 );
+
+acttable_t CWeaponMG42::m_acttable[] =
+{
+ { ACT_DOD_STAND_AIM, ACT_DOD_STAND_AIM_MG, false },
+ { ACT_DOD_CROUCH_AIM, ACT_DOD_CROUCH_AIM_MG, false },
+ { ACT_DOD_CROUCHWALK_AIM, ACT_DOD_CROUCHWALK_AIM_MG, false },
+ { ACT_DOD_WALK_AIM, ACT_DOD_WALK_AIM_MG, false },
+ { ACT_DOD_RUN_AIM, ACT_DOD_RUN_AIM_MG, false },
+ { ACT_PRONE_IDLE, ACT_DOD_PRONE_AIM_MG, false },
+ { ACT_PRONE_FORWARD, ACT_DOD_PRONEWALK_IDLE_MG, false },
+ { ACT_DOD_STAND_IDLE, ACT_DOD_STAND_IDLE_MG, false },
+ { ACT_DOD_CROUCH_IDLE, ACT_DOD_CROUCH_IDLE_MG, false },
+ { ACT_DOD_CROUCHWALK_IDLE, ACT_DOD_CROUCHWALK_IDLE_MG, false },
+ { ACT_DOD_WALK_IDLE, ACT_DOD_WALK_IDLE_MG, false },
+ { ACT_DOD_RUN_IDLE, ACT_DOD_RUN_IDLE_MG, false },
+ { ACT_SPRINT, ACT_DOD_SPRINT_IDLE_MG, false },
+
+ // Deployed Aim
+ { ACT_DOD_DEPLOYED, ACT_DOD_DEPLOY_MG, false },
+ { ACT_DOD_PRONE_DEPLOYED, ACT_DOD_PRONE_DEPLOY_MG, false },
+
+ // Attack ( prone? deployed? )
+ { ACT_RANGE_ATTACK1, ACT_DOD_PRIMARYATTACK_MG, false },
+ { ACT_DOD_PRIMARYATTACK_CROUCH, ACT_DOD_PRIMARYATTACK_MG, false },
+ { ACT_DOD_PRIMARYATTACK_PRONE, ACT_DOD_PRIMARYATTACK_PRONE_MG, false },
+ { ACT_DOD_PRIMARYATTACK_DEPLOYED, ACT_DOD_PRIMARYATTACK_DEPLOYED_MG, false },
+ { ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED, ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_MG,false },
+
+ // Reload ( prone? deployed? )
+ { ACT_DOD_RELOAD_DEPLOYED, ACT_DOD_RELOAD_DEPLOYED_MG, false },
+ { ACT_DOD_RELOAD_PRONE_DEPLOYED, ACT_DOD_RELOAD_PRONE_DEPLOYED_MG, false },
+
+ // Hand Signals
+ { ACT_DOD_HS_IDLE, ACT_DOD_HS_IDLE_MG42, false },
+ { ACT_DOD_HS_CROUCH, ACT_DOD_HS_CROUCH_MG42, false },
+};
+
+IMPLEMENT_ACTTABLE( CWeaponMG42 );
+
+void CWeaponMG42::Spawn( void )
+{
+ m_iWeaponHeat = 0;
+ m_flNextCoolTime = 0;
+
+ m_bOverheated = false;
+
+#ifdef CLIENT_DLL
+ m_pEmitter = NULL;
+ m_flParticleAccumulator = 0.0;
+ m_hParticleMaterial = ParticleMgr()->GetPMaterial( "sprites/effects/bazookapuff" );
+#endif
+
+ BaseClass::Spawn();
+}
+
+#ifdef CLIENT_DLL
+
+ CWeaponMG42::~CWeaponMG42()
+ {
+ if ( clienttools->IsInRecordingMode() && m_pEmitter.IsValid() && m_pEmitter->GetToolParticleEffectId() != TOOLPARTICLESYSTEMID_INVALID )
+ {
+ KeyValues *msg = new KeyValues( "ParticleSystem_ActivateEmitter" );
+ msg->SetInt( "id", m_pEmitter->GetToolParticleEffectId() );
+ msg->SetFloat( "time", gpGlobals->curtime );
+ msg->SetInt( "active", 0 );
+
+ msg->SetInt( "emitter", 0 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 1 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 2 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 3 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->deleteThis();
+ }
+ }
+
+ void CWeaponMG42::OnDataChanged( DataUpdateType_t updateType )
+ {
+ BaseClass::OnDataChanged( updateType );
+
+ // BUG! This can happen more than once!
+ if ( updateType == DATA_UPDATE_CREATED )
+ {
+ if ( !m_pEmitter.IsValid() )
+ {
+ m_pEmitter = CSimpleEmitter::Create( "MGOverheat" );
+ }
+
+ Assert( m_pEmitter.IsValid() );
+ }
+
+ ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_ALWAYS );
+ }
+
+ // Client Think emits smoke particles based on heat
+ // ( except if we are holstered )
+ void CWeaponMG42::ClientThink( void )
+ {
+ m_pEmitter->SetSortOrigin( GetAbsOrigin() );
+
+ float flEmitRate = 0.0; //particles per second
+
+ // Only smoke if we are dropped ( no owner ) or if we have an owner and are active
+ if ( GetOwner() == NULL || GetOwner()->GetActiveWeapon() == this )
+ {
+ if ( m_iWeaponHeat > 85 )
+ {
+ flEmitRate = 30;
+ }
+ else if ( m_iWeaponHeat > 80 )
+ {
+ flEmitRate = 20;
+ }
+ else if ( m_iWeaponHeat > 65 )
+ {
+ flEmitRate = 10;
+ }
+ else if ( m_iWeaponHeat > 50 )
+ {
+ flEmitRate = 5;
+ }
+ }
+
+ m_flParticleAccumulator += ( gpGlobals->frametime * flEmitRate );
+
+ while( m_flParticleAccumulator > 0.0 )
+ {
+ EmitSmokeParticle();
+
+ m_flParticleAccumulator -= 1.0;
+ }
+ }
+
+ void CWeaponMG42::EmitSmokeParticle( void )
+ {
+ Vector vFront, vBack;
+ QAngle angles;
+
+ C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
+
+ bool bViewModel = false;
+
+ // if this is locally owned
+ if ( GetPlayerOwner() == pLocalPlayer )
+ {
+ C_BaseViewModel *vm = pLocalPlayer->GetViewModel( 0 );
+
+ if ( !vm )
+ return;
+
+ vm->GetAttachment( 1, vFront, angles );
+ vm->GetAttachment( 2, vBack, angles );
+
+ bViewModel = true;
+ }
+ else
+ {
+ // could be dropped, or held by another player
+ GetAttachment( 1, vFront, angles );
+ GetAttachment( 2, vBack, angles );
+ }
+
+ // Get a position somewhere on the barrel
+ Vector vPos = vBack + random->RandomFloat(0.0, 1.0 ) * ( vFront - vBack );
+
+ SimpleParticle *pParticle = m_pEmitter->AddSimpleParticle( m_hParticleMaterial, vPos );
+ if ( pParticle )
+ {
+ pParticle->m_vecVelocity = Vector( 0,0,12 );
+ pParticle->m_flRoll = random->RandomFloat( 0, 0.5 );
+ pParticle->m_flRollDelta = ( random->RandomInt(0,1) == 0 ? 1 : -1 ) * random->RandomFloat( 0.5, 1.0 );
+ pParticle->m_flDieTime = 1.8f;
+ pParticle->m_flLifetime = 0;
+ pParticle->m_uchColor[0] = 200;
+ pParticle->m_uchColor[1] = 200;
+ pParticle->m_uchColor[2] = 200;
+ pParticle->m_uchStartAlpha = 60;
+ pParticle->m_uchEndAlpha = 0;
+ pParticle->m_uchStartSize = 4;
+ pParticle->m_uchEndSize = 25;
+ pParticle->m_iFlags = 0; //bViewModel ? FLE_VIEWMODEL : 0;
+ }
+ }
+
+#else
+
+ // This function does the cooling when the weapon is dropped or holstered
+ // regular, predicted cooling is done in ItemPostFrame
+ void CWeaponMG42::CoolThink( void )
+ {
+ if ( m_iWeaponHeat > 0 )
+ m_iWeaponHeat--;
+
+ SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
+ }
+
+#endif
+
+void CWeaponMG42::Precache()
+{
+ PrecacheMaterial( "sprites/effects/bazookapuff" );
+
+ PrecacheScriptSound( "Weapon_Mg42.OverHeat" );
+
+ BaseClass::Precache();
+}
+
+bool CWeaponMG42::Reload( void )
+{
+ if( !IsDeployed() )
+ {
+#ifdef CLIENT_DLL
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+
+ if ( pPlayer )
+ pPlayer->HintMessage( HINT_MG_DEPLOY_TO_RELOAD );
+#endif
+ return false;
+ }
+
+ return BaseClass::Reload();
+}
+
+void CWeaponMG42::FinishReload( void )
+{
+ BaseClass::FinishReload();
+
+ //Reset the heat when you complete a reload
+ m_iWeaponHeat = 0;
+}
+
+void CWeaponMG42::PrimaryAttack( void )
+{
+ if( m_bOverheated )
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 0 )
+ {
+ if (m_bFireOnEmpty)
+ {
+ PlayEmptySound();
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
+ }
+
+ return;
+ }
+
+
+ CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
+ Assert( pPlayer );
+
+ if( m_iWeaponHeat >= 99 )
+ {
+ //can't fire anymore, wait until heat is below 80
+#ifdef CLIENT_DLL
+ pPlayer->HintMessage( HINT_WEAPON_OVERHEAT );
+#endif
+ m_bOverheated = true;
+ m_bInAttack = true;
+
+ EmitSound( "Weapon_Mg42.OverHeat" );
+ return;
+ }
+
+ m_iWeaponHeat += 1; //2;
+ m_flNextCoolTime = gpGlobals->curtime + 0.16f;
+
+ if( !IsDeployed() )
+ {
+#ifdef CLIENT_DLL
+ pPlayer->HintMessage( HINT_MG_FIRE_UNDEPLOYED );
+#endif
+ pPlayer->m_Shared.SetSlowedTime( 0.2 );
+
+ float flStamina = pPlayer->m_Shared.GetStamina();
+
+ pPlayer->m_Shared.SetStamina( flStamina - 15 );
+ }
+
+ BaseClass::PrimaryAttack();
+}
+
+void CWeaponMG42::ItemPostFrame( void )
+{
+ ItemFrameCool();
+
+ if( m_iWeaponHeat < 80 )
+ m_bOverheated = false;
+
+ BaseClass::ItemPostFrame();
+}
+
+void CWeaponMG42::ItemBusyFrame( void )
+{
+ ItemFrameCool();
+
+ BaseClass::ItemBusyFrame();
+}
+
+void CWeaponMG42::ItemFrameCool( void )
+{
+ if( gpGlobals->curtime > m_flNextCoolTime )
+ {
+ if ( m_iWeaponHeat > 0 )
+ m_iWeaponHeat--;
+
+ m_flNextCoolTime = gpGlobals->curtime + 0.16f;
+ }
+}
+
+bool CWeaponMG42::Deploy( void )
+{
+ // stop the fake cooling when we deploy the weapon
+ SetContextThink( NULL, 0.0, COOL_CONTEXT );
+
+ return BaseClass::Deploy();
+}
+
+bool CWeaponMG42::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+#ifndef CLIENT_DLL
+ SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
+#endif
+
+ return BaseClass::Holster(pSwitchingTo);
+}
+
+void CWeaponMG42::Drop( const Vector &vecVelocity )
+{
+#ifndef CLIENT_DLL
+ SetContextThink( &CWeaponMG42::CoolThink, gpGlobals->curtime + 0.1, COOL_CONTEXT );
+#endif
+
+ BaseClass::Drop( vecVelocity );
+}
+
+Activity CWeaponMG42::GetReloadActivity( void )
+{
+ return ACT_VM_RELOAD;
+}
+
+Activity CWeaponMG42::GetDrawActivity( void )
+{
+ Activity actDraw;
+
+ if( 0 && m_iClip1 <= 0 )
+ actDraw = ACT_VM_DRAW_EMPTY;
+ else
+ actDraw = ACT_VM_DRAW;
+
+ return actDraw;
+}
+
+Activity CWeaponMG42::GetDeployActivity( void )
+{
+ Activity actDeploy;
+
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actDeploy = ACT_VM_DEPLOY_8;
+ break;
+ case 7:
+ actDeploy = ACT_VM_DEPLOY_7;
+ break;
+ case 6:
+ actDeploy = ACT_VM_DEPLOY_6;
+ break;
+ case 5:
+ actDeploy = ACT_VM_DEPLOY_5;
+ break;
+ case 4:
+ actDeploy = ACT_VM_DEPLOY_4;
+ break;
+ case 3:
+ actDeploy = ACT_VM_DEPLOY_3;
+ break;
+ case 2:
+ actDeploy = ACT_VM_DEPLOY_2;
+ break;
+ case 1:
+ actDeploy = ACT_VM_DEPLOY_1;
+ break;
+ case 0:
+ actDeploy = ACT_VM_DEPLOY_EMPTY;
+ break;
+ default:
+ actDeploy = ACT_VM_DEPLOY;
+ break;
+ }
+
+ return actDeploy;
+}
+
+Activity CWeaponMG42::GetUndeployActivity( void )
+{
+ Activity actUndeploy;
+
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actUndeploy = ACT_VM_UNDEPLOY_8;
+ break;
+ case 7:
+ actUndeploy = ACT_VM_UNDEPLOY_7;
+ break;
+ case 6:
+ actUndeploy = ACT_VM_UNDEPLOY_6;
+ break;
+ case 5:
+ actUndeploy = ACT_VM_UNDEPLOY_5;
+ break;
+ case 4:
+ actUndeploy = ACT_VM_UNDEPLOY_4;
+ break;
+ case 3:
+ actUndeploy = ACT_VM_UNDEPLOY_3;
+ break;
+ case 2:
+ actUndeploy = ACT_VM_UNDEPLOY_2;
+ break;
+ case 1:
+ actUndeploy = ACT_VM_UNDEPLOY_1;
+ break;
+ case 0:
+ actUndeploy = ACT_VM_UNDEPLOY_EMPTY;
+ break;
+ default:
+ actUndeploy = ACT_VM_UNDEPLOY;
+ break;
+ }
+
+ return actUndeploy;
+}
+
+Activity CWeaponMG42::GetIdleActivity( void )
+{
+ Activity actIdle;
+
+ if( IsDeployed() )
+ {
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actIdle = ACT_VM_IDLE_DEPLOYED_8;
+ break;
+ case 7:
+ actIdle = ACT_VM_IDLE_DEPLOYED_7;
+ break;
+ case 6:
+ actIdle = ACT_VM_IDLE_DEPLOYED_6;
+ break;
+ case 5:
+ actIdle = ACT_VM_IDLE_DEPLOYED_5;
+ break;
+ case 4:
+ actIdle = ACT_VM_IDLE_DEPLOYED_4;
+ break;
+ case 3:
+ actIdle = ACT_VM_IDLE_DEPLOYED_3;
+ break;
+ case 2:
+ actIdle = ACT_VM_IDLE_DEPLOYED_2;
+ break;
+ case 1:
+ actIdle = ACT_VM_IDLE_DEPLOYED_1;
+ break;
+ case 0:
+ actIdle = ACT_VM_IDLE_DEPLOYED_EMPTY;
+ break;
+ default:
+ actIdle = ACT_VM_IDLE_DEPLOYED;
+ break;
+ }
+ }
+ else
+ {
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actIdle = ACT_VM_IDLE_8;
+ break;
+ case 7:
+ actIdle = ACT_VM_IDLE_7;
+ break;
+ case 6:
+ actIdle = ACT_VM_IDLE_6;
+ break;
+ case 5:
+ actIdle = ACT_VM_IDLE_5;
+ break;
+ case 4:
+ actIdle = ACT_VM_IDLE_4;
+ break;
+ case 3:
+ actIdle = ACT_VM_IDLE_3;
+ break;
+ case 2:
+ actIdle = ACT_VM_IDLE_2;
+ break;
+ case 1:
+ actIdle = ACT_VM_IDLE_1;
+ break;
+ case 0:
+ actIdle = ACT_VM_IDLE_EMPTY;
+ break;
+ default:
+ actIdle = ACT_VM_IDLE;
+ break;
+ }
+ }
+
+ return actIdle;
+}
+
+Activity CWeaponMG42::GetPrimaryAttackActivity( void )
+{
+ Activity actPrim;
+
+ if( IsDeployed() )
+ {
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_8;
+ break;
+ case 7:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_7;
+ break;
+ case 6:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_6;
+ break;
+ case 5:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_5;
+ break;
+ case 4:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_4;
+ break;
+ case 3:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_3;
+ break;
+ case 2:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_2;
+ break;
+ case 1:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_1;
+ break;
+ case 0:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED_EMPTY;
+ break;
+ default:
+ actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED;
+ break;
+ }
+ }
+ else
+ {
+ switch ( m_iClip1 )
+ {
+ case 8:
+ actPrim = ACT_VM_PRIMARYATTACK_8;
+ break;
+ case 7:
+ actPrim = ACT_VM_PRIMARYATTACK_7;
+ break;
+ case 6:
+ actPrim = ACT_VM_PRIMARYATTACK_6;
+ break;
+ case 5:
+ actPrim = ACT_VM_PRIMARYATTACK_5;
+ break;
+ case 4:
+ actPrim = ACT_VM_PRIMARYATTACK_4;
+ break;
+ case 3:
+ actPrim = ACT_VM_PRIMARYATTACK_3;
+ break;
+ case 2:
+ actPrim = ACT_VM_PRIMARYATTACK_2;
+ break;
+ case 1:
+ actPrim = ACT_VM_PRIMARYATTACK_1;
+ break;
+ case 0:
+ actPrim = ACT_VM_PRIMARYATTACK_EMPTY;
+ break;
+ default:
+ actPrim = ACT_VM_PRIMARYATTACK;
+ break;
+ }
+ }
+
+ return actPrim;
+}
+
+float CWeaponMG42::GetRecoil( void )
+{
+ CDODPlayer *p = ToDODPlayer( GetPlayerOwner() );
+
+ if( p && p->m_Shared.IsInMGDeploy() )
+ {
+ return 0.0f;
+ }
+
+ return 20;
+}
+
+#ifdef CLIENT_DLL
+
+//-----------------------------------------------------------------------------
+// This is called after sending this entity's recording state
+//-----------------------------------------------------------------------------
+void CWeaponMG42::CleanupToolRecordingState( KeyValues *msg )
+{
+ BaseClass::CleanupToolRecordingState( msg );
+
+ // Generally, this is used to allow the entity to clean up
+ // allocated state it put into the message, but here we're going
+ // to use it to send particle system messages because we
+ // know the smoke has been recorded at this point
+ if ( !clienttools->IsInRecordingMode() || !m_pEmitter.IsValid() )
+ return;
+
+ // NOTE: Particle system destruction message will be sent by the particle effect itself.
+ if ( m_pEmitter->GetToolParticleEffectId() == TOOLPARTICLESYSTEMID_INVALID )
+ {
+ int nId = m_pEmitter->AllocateToolParticleEffectId();
+
+ KeyValues *msg = new KeyValues( "ParticleSystem_Create" );
+ msg->SetString( "name", "CWeaponMG42 smoke" );
+ msg->SetInt( "id", nId );
+ msg->SetFloat( "time", gpGlobals->curtime );
+
+ KeyValues *pEmitter0 = msg->FindKey( "DmeSpriteEmitter", true );
+ pEmitter0->SetInt( "count", 5 ); // particles per second, when duration is < 0
+ pEmitter0->SetFloat( "duration", -1 );
+ pEmitter0->SetString( "material", "sprites/effects/bazookapuff" );
+ pEmitter0->SetInt( "active", 0 );
+
+ KeyValues *pInitializers = pEmitter0->FindKey( "initializers", true );
+
+ KeyValues *pPosition = pInitializers->FindKey( "DmeRandomAttachmentPositionEntityInitializer", true );
+ pPosition->SetPtr( "entindex", (void*)entindex() );
+ pPosition->SetInt( "attachmentIndex0", 1 );
+ pPosition->SetInt( "attachmentIndex1", 2 );
+
+ KeyValues *pLifetime = pInitializers->FindKey( "DmeRandomLifetimeInitializer", true );
+ pLifetime->SetFloat( "minLifetime", 1.8f );
+ pLifetime->SetFloat( "maxLifetime", 1.8f );
+
+ KeyValues *pVelocity = pInitializers->FindKey( "DmeConstantVelocityInitializer", true );
+ pVelocity->SetFloat( "velocityX", 0.0f );
+ pVelocity->SetFloat( "velocityY", 0.0f );
+ pVelocity->SetFloat( "velocityZ", 12.0f );
+
+ KeyValues *pRoll = pInitializers->FindKey( "DmeRandomRollInitializer", true );
+ pRoll->SetFloat( "minRoll", 0.0f );
+ pRoll->SetFloat( "maxRoll", 0.5f );
+
+ KeyValues *pRollSpeed = pInitializers->FindKey( "DmeSplitRandomRollSpeedInitializer", true );
+ pRollSpeed->SetFloat( "minRollSpeed", 0.5f );
+ pRollSpeed->SetFloat( "maxRollSpeed", 1.0f );
+
+ KeyValues *pColor = pInitializers->FindKey( "DmeRandomInterpolatedColorInitializer", true );
+ pColor->SetColor( "color1", Color( 200, 200, 200, 255 ) );
+ pColor->SetColor( "color2", Color( 200, 200, 200, 255 ) );
+
+ KeyValues *pAlpha = pInitializers->FindKey( "DmeRandomAlphaInitializer", true );
+ pAlpha->SetInt( "minStartAlpha", 60 );
+ pAlpha->SetInt( "maxStartAlpha", 60 );
+ pAlpha->SetInt( "minEndAlpha", 0 );
+ pAlpha->SetInt( "maxEndAlpha", 0 );
+
+ KeyValues *pSize = pInitializers->FindKey( "DmeRandomSizeInitializer", true );
+ pSize->SetFloat( "minStartSize", 4 );
+ pSize->SetFloat( "maxStartSize", 4 );
+ pSize->SetFloat( "minEndSize", 25 );
+ pSize->SetFloat( "maxEndSize", 25 );
+
+ KeyValues *pUpdaters = pEmitter0->FindKey( "updaters", true );
+
+ pUpdaters->FindKey( "DmePositionVelocityUpdater", true );
+ pUpdaters->FindKey( "DmeRollUpdater", true );
+ pUpdaters->FindKey( "DmeAlphaLinearUpdater", true );
+ pUpdaters->FindKey( "DmeSizeUpdater", true );
+
+ // create emitters for each emission rate: 5,10,20,30
+ KeyValues *pEmitter1 = pEmitter0->MakeCopy();
+ pEmitter1->SetInt( "count", 10 );
+ msg->AddSubKey( pEmitter1 );
+
+ KeyValues *pEmitter2 = pEmitter0->MakeCopy();
+ pEmitter2->SetInt( "count", 20 );
+ msg->AddSubKey( pEmitter2 );
+
+ KeyValues *pEmitter3 = pEmitter0->MakeCopy();
+ pEmitter3->SetInt( "count", 30 );
+ msg->AddSubKey( pEmitter3 );
+
+ // mark only the appropriate emitter active
+ bool bHolstered = GetOwner() && GetOwner()->GetActiveWeapon() != this;
+ if ( !bHolstered )
+ {
+ if ( m_iWeaponHeat > 85 )
+ {
+ pEmitter3->SetInt( "active", 1 );
+ }
+ else if ( m_iWeaponHeat > 80 )
+ {
+ pEmitter2->SetInt( "active", 1 );
+ }
+ else if ( m_iWeaponHeat > 65 )
+ {
+ pEmitter1->SetInt( "active", 1 );
+ }
+ else if ( m_iWeaponHeat > 50 )
+ {
+ pEmitter0->SetInt( "active", 1 );
+ }
+ }
+
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+ msg->deleteThis();
+ }
+ else
+ {
+ int nEmitterIndex = -1;
+ bool bHolstered = GetOwner() && GetOwner()->GetActiveWeapon() != this;
+ if ( !bHolstered )
+ {
+ if ( m_iWeaponHeat > 85 )
+ {
+ nEmitterIndex = 3;
+ }
+ else if ( m_iWeaponHeat > 80 )
+ {
+ nEmitterIndex = 2;
+ }
+ else if ( m_iWeaponHeat > 65 )
+ {
+ nEmitterIndex = 1;
+ }
+ else if ( m_iWeaponHeat > 50 )
+ {
+ nEmitterIndex = 0;
+ }
+ }
+
+ KeyValues *msg = new KeyValues( "ParticleSystem_ActivateEmitter" );
+ msg->SetInt( "id", m_pEmitter->GetToolParticleEffectId() );
+ msg->SetFloat( "time", gpGlobals->curtime );
+
+ msg->SetInt( "emitter", 0 );
+ msg->SetInt( "active", nEmitterIndex == 0 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 1 );
+ msg->SetInt( "active", nEmitterIndex == 1 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 2 );
+ msg->SetInt( "active", nEmitterIndex == 2 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->SetInt( "emitter", 3 );
+ msg->SetInt( "active", nEmitterIndex == 3 );
+ ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
+
+ msg->deleteThis();
+ }
+}
+
+#endif