//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFWeaponBaseGun::ItemPostFrame( void ) { int iOldBurstSize = m_iBurstSize; CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner ) { if ( m_iBurstSize > 0 ) { // Fake the fire button. pOwner->m_nButtons |= IN_ATTACK; } } BaseClass::ItemPostFrame(); // Stop burst if we run out of ammo. if ( ( UsesClipsForAmmo1() && m_iClip1 <= 0 ) || ( !UsesClipsForAmmo1() && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) ) { m_iBurstSize = 0; } if ( iOldBurstSize > 0 && m_iBurstSize == 0 ) { // Delay the next burst. m_flNextPrimaryAttack = gpGlobals->curtime + m_pWeaponInfo->GetWeaponData( TF_WEAPON_PRIMARY_MODE ).m_flBurstDelay; } }
// ---------------------------------------------------------------------------- - // Purpose: //----------------------------------------------------------------------------- void CTFCompoundBow::PrimaryAttack( void ) { if ( !CanAttack() ) { m_flChargeBeginTime = 0; return; } if ( m_flChargeBeginTime <= 0 ) { // Set the weapon mode. m_iWeaponMode = TF_WEAPON_PRIMARY_MODE; // save that we had the attack button down m_flChargeBeginTime = gpGlobals->curtime; SendWeaponAnim( ACT_ITEM2_VM_CHARGE ); CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner ) { WeaponSound( SPECIAL1 ); pOwner->m_Shared.AddCond( TF_COND_AIMING ); pOwner->TeamFortress_SetSpeed(); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFSniperRifle::ZoomOut( void ) { BaseClass::ZoomOut(); // Stop aiming CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; pPlayer->m_Shared.RemoveCond( TF_COND_AIMING ); pPlayer->TeamFortress_SetSpeed(); #ifdef GAME_DLL // Destroy the sniper dot. DestroySniperDot(); pPlayer->ClearExpression(); #endif // if we are thinking about zooming, cancel it m_flUnzoomTime = -1; m_flRezoomTime = -1; m_bRezoomAfterShot = false; m_flChargedDamage = 0.0f; }
// ---------------------------------------------------------------------------- - // Purpose: //----------------------------------------------------------------------------- void CTFCompoundBow::FireArrow( void ) { // Get the player owning the weapon. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; CalcIsAttackCritical(); SendWeaponAnim( ACT_VM_PRIMARYATTACK ); pPlayer->SetAnimation( PLAYER_ATTACK1 ); pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY ); pPlayer->m_Shared.RemoveCond( TF_COND_AIMING ); pPlayer->TeamFortress_SetSpeed(); FireProjectile( pPlayer ); #if !defined( CLIENT_DLL ) pPlayer->SpeakWeaponFire(); CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACrit() ); #endif // Set next attack times. float flDelay = m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_flTimeFireDelay; CALL_ATTRIB_HOOK_FLOAT( flDelay, mult_postfiredelay ); m_flNextPrimaryAttack = gpGlobals->curtime + flDelay; SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); m_flChargeBeginTime = 0.0f; }
// ----------------------------------------------------------------------------- // Purpose: // ----------------------------------------------------------------------------- bool CTFWeaponBaseMelee::CanHolster( void ) const { if ( GetTFPlayerOwner()->m_Shared.InCond( TF_COND_CANNOT_SWITCH_FROM_MELEE ) ) return false; return BaseClass::CanHolster(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponMedigun::AddCharge( void ) { #ifdef GAME_DLL CTFPlayer *pPlayer = GetTFPlayerOwner(); CTFPlayer *pHealingTarget = ToTFPlayer( m_hHealingTarget ); #endif float flNewLevel = min( m_flChargeLevel + 0.25, 1.0 ); if ( flNewLevel >= 1.0 && m_flChargeLevel < 1.0 ) { #ifdef GAME_DLL if ( pPlayer ) { pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_MEDIC_CHARGEREADY ); } if ( pHealingTarget ) { pHealingTarget->SpeakConceptIfAllowed( MP_CONCEPT_HEALTARGET_CHARGEREADY ); } #endif } m_flChargeLevel = flNewLevel; }
bool CTFHunterRifle::IsZoomed( void ) { CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer ) { return pPlayer->m_Shared.InCond( TF_COND_AIMING ); } return false; }
bool CTFSniperRifle::IsZoomed( void ) { CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer ) { return pPlayer->m_Shared.InCond( TF_COND_ZOOMED ); } return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFWeaponBuilder::CanHolster( void ) const { // If player is hauling a building he can't switch away without dropping it. CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner && pOwner->m_Shared.IsCarryingObject() ) { return false; } return BaseClass::CanHolster(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFCompoundBow::WeaponIdle( void ) { CTFPlayer *pOwner = GetTFPlayerOwner(); if ( m_flChargeBeginTime > 0 && pOwner->GetAmmoCount( GetPrimaryAmmoType() ) > 0 ) { FireArrow(); } else { BaseClass::WeaponIdle(); } }
//----------------------------------------------------------------------------- // Purpose: Secondary attack. //----------------------------------------------------------------------------- void CTFHunterRifle::Zoom( void ) { // Don't allow the player to zoom in while jumping CTFPlayer *pPlayer = GetTFPlayerOwner(); if (!pPlayer) return; ToggleZoom(); // at least 0.1 seconds from now, but don't stomp a previous value m_flNextPrimaryAttack = max( m_flNextPrimaryAttack, gpGlobals->curtime + 0.1 ); m_flNextSecondaryAttack = gpGlobals->curtime + TF_WEAPON_HUNTERRIFLE_ZOOM_TIME; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFHunterRifle::ZoomOutIn( void ) { ZoomOut(); CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer && pPlayer->ShouldAutoRezoom() ) { m_flRezoomTime = gpGlobals->curtime + 0.9; } else { m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFHunterRifle::CanHolster( void ) const { CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer ) { // don't allow us to holster this weapon if we're in the process of zooming and // we've just fired the weapon (next primary attack is only 1.5 seconds after firing) if ( ( pPlayer->GetFOV() < pPlayer->GetDefaultFOV() ) && ( m_flNextPrimaryAttack > gpGlobals->curtime ) ) { return false; } } return BaseClass::CanHolster(); }
void CTFBonesaw::UpdateChargePoseParam( void ) { CTFPlayer *pOwner = GetTFPlayerOwner(); if ( !pOwner ) return; CWeaponMedigun *pMedigun = pOwner->GetMedigun(); if ( pMedigun ) { SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm ) vm->SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); } }
//----------------------------------------------------------------------------- // Purpose: Secondary attack. //----------------------------------------------------------------------------- void CTFSniperRifle::Zoom( void ) { // Don't allow the player to zoom in while jumping CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer && pPlayer->m_Shared.IsJumping() ) { if ( pPlayer->GetFOV() >= 75 ) return; } ToggleZoom(); // at least 0.1 seconds from now, but don't stomp a previous value m_flNextPrimaryAttack = max( m_flNextPrimaryAttack, gpGlobals->curtime + 0.1 ); m_flNextSecondaryAttack = gpGlobals->curtime + TF_WEAPON_SNIPERRIFLE_ZOOM_TIME; }
// ----------------------------------------------------------------------------- // Purpose: // ----------------------------------------------------------------------------- void CTFWeaponBaseMelee::SecondaryAttack() { // semi-auto behaviour if ( m_bInAttack2 ) return; // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; pPlayer->DoClassSpecialSkill(); m_bInAttack2 = true; m_flNextSecondaryAttack = gpGlobals->curtime + 0.5; }
bool CTFRevolver::DefaultReload( int iClipSize1, int iClipSize2, int iActivity ) { // The the owning local player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return false; if ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) ) { if ( pPlayer->m_Shared.InCond( TF_COND_STEALTHED ) ) { return false; } } return BaseClass::DefaultReload( iClipSize1, iClipSize2, iActivity ); }
// ----------------------------------------------------------------------------- // Purpose: // ----------------------------------------------------------------------------- void CTFHammerfists::Punch( void ) { // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; // Swing the weapon. Swing( pPlayer ); m_flNextSecondaryAttack = m_flNextPrimaryAttack; #if !defined( CLIENT_DLL ) // We might or might not add Merc voice lines for ragemode, so just leave this in pPlayer->SpeakWeaponFire(); #endif }
//----------------------------------------------------------------------------- // Purpose: Stop placement when holstering //----------------------------------------------------------------------------- bool CTFWeaponBuilder::Holster( CBaseCombatWeapon *pSwitchingTo ) { if ( m_iBuildState == BS_PLACING || m_iBuildState == BS_PLACING_INVALID ) { SetCurrentState( BS_IDLE ); } StopPlacement(); // Make sure hauling status is cleared. CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner && pOwner->m_Shared.IsCarryingObject() ) { pOwner->m_Shared.SetCarriedObject( NULL ); } return BaseClass::Holster(pSwitchingTo); }
void CTFChainsaw::PrimaryAttack(void) { // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; if ( !CanAttack() ) return; // Set the weapon usage mode - primary, secondary. m_iWeaponMode = TF_WEAPON_PRIMARY_MODE; m_bConnected = false; bIsAttacking = true; BaseClass::PrimaryAttack(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFHunterRifle::ZoomIn( void ) { // Start aiming. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 || Clip1() <= 0) return; pPlayer->SetFOV(pPlayer, TF_WEAPON_ZOOM_FOV, 0.1f); //BaseClass::ZoomIn(); pPlayer->m_Shared.AddCond( TF_COND_AIMING ); pPlayer->TeamFortress_SetSpeed(); }
// ---------------------------------------------------------------------------- - // Purpose: Cancel shot charging. //----------------------------------------------------------------------------- void CTFCompoundBow::LowerBow( void ) { if ( m_flChargeBeginTime == 0.0f ) return; m_flChargeBeginTime = 0.0f; CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner ) { pOwner->m_Shared.RemoveCond( TF_COND_AIMING ); pOwner->TeamFortress_SetSpeed(); } // Delay the next fire so they don't immediately start charging again. m_flNextPrimaryAttack = gpGlobals->curtime + 1.0f; SendWeaponAnim( ACT_ITEM2_VM_DRYFIRE ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFHunterRifle::ZoomOut( void ) { //BaseClass::ZoomOut(); // Stop aiming CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; pPlayer->SetFOV(pPlayer, 0, 0.1f); pPlayer->m_Shared.RemoveCond( TF_COND_AIMING ); pPlayer->TeamFortress_SetSpeed(); // if we are thinking about zooming, cancel it m_flUnzoomTime = -1; m_flRezoomTime = -1; m_bRezoomAfterShot = false; m_flChargedSpread = TF_WEAPON_HUNTERRIFLE_SPREAD_MAX; }
bool CTFWeaponBaseMelee::DoSwingTrace( trace_t &trace ) { // Setup a volume for the melee weapon to be swung - approx size, so all melee behave the same. static Vector vecSwingMins( -18, -18, -18 ); static Vector vecSwingMaxs( 18, 18, 18 ); // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return false; // Setup the swing range. Vector vecForward; AngleVectors( pPlayer->EyeAngles(), &vecForward ); Vector vecSwingStart = pPlayer->Weapon_ShootPosition(); Vector vecSwingEnd = vecSwingStart + vecForward * 48; // See if we hit anything. UTIL_TraceLine( vecSwingStart, vecSwingEnd, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction >= 1.0 ) { UTIL_TraceHull( vecSwingStart, vecSwingEnd, vecSwingMins, vecSwingMaxs, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = trace.m_pEnt; if ( !pHit || pHit->IsBSPModel() ) { // Why duck hull min/max? FindHullIntersection( vecSwingStart, trace, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer ); } // This is the point on the actual surface (the hull could have hit space) vecSwingEnd = trace.endpos; } } return ( trace.fraction < 1.0f ); }
// ----------------------------------------------------------------------------- // Purpose: // ----------------------------------------------------------------------------- void CTFWeaponBaseMelee::PrimaryAttack() { // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; if ( !CanAttack() ) return; // Set the weapon usage mode - primary, secondary. m_iWeaponMode = TF_WEAPON_PRIMARY_MODE; m_bConnected = false; // Swing the weapon. Swing( pPlayer ); #if !defined( CLIENT_DLL ) pPlayer->SpeakWeaponFire(); CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACritical() ); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFSniperRifle::ZoomIn( void ) { // Start aiming. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) return; BaseClass::ZoomIn(); pPlayer->m_Shared.AddCond( TF_COND_AIMING ); pPlayer->TeamFortress_SetSpeed(); #ifdef GAME_DLL // Create the sniper dot. CreateSniperDot(); pPlayer->ClearExpression(); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFHunterRifle::CanFireCriticalShot( bool bIsHeadshot ) { // can only fire a crit shot if this is a headshot if ( !bIsHeadshot ) return false; CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( pPlayer ) { // no crits if they're not zoomed if ( pPlayer->GetFOV() >= pPlayer->GetDefaultFOV() ) { return false; } // no crits for 0.2 seconds after starting to zoom if ( ( gpGlobals->curtime - pPlayer->GetFOVTime() ) < TF_WEAPON_HUNTERRIFLE_NO_CRIT_AFTER_ZOOM_TIME ) { return false; } } return true; }
// ----------------------------------------------------------------------------- // Purpose: // Note: Think function to delay the impact decal until the animation is finished // playing. // ----------------------------------------------------------------------------- void CTFWeaponBaseMelee::Smack( void ) { trace_t trace; CBasePlayer *pPlayer = GetPlayerOwner(); if ( !pPlayer ) return; #if !defined (CLIENT_DLL) // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); #endif // We hit, setup the smack. if ( DoSwingTrace( trace ) ) { // Hit sound - immediate. if( trace.m_pEnt->IsPlayer() ) { WeaponSound( MELEE_HIT ); } else { WeaponSound( MELEE_HIT_WORLD ); } // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; Vector vecForward; AngleVectors( pPlayer->EyeAngles(), &vecForward ); Vector vecSwingStart = pPlayer->Weapon_ShootPosition(); Vector vecSwingEnd = vecSwingStart + vecForward * 48; #ifndef CLIENT_DLL // Do Damage. int iCustomDamage = TF_DMG_CUSTOM_NONE; float flDamage = GetMeleeDamage( trace.m_pEnt, iCustomDamage ); int iDmgType = DMG_BULLET | DMG_NEVERGIB | DMG_CLUB; if ( IsCurrentAttackACrit() ) { // TODO: Not removing the old critical path yet, but the new custom damage is marking criticals as well for melee now. iDmgType |= DMG_CRITICAL; } CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); CTFUbersaw *pUbersaw = dynamic_cast<CTFUbersaw*>(pWpn); CWeaponMedigun *pMedigun = static_cast<CWeaponMedigun*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_MEDIGUN)); if (pMedigun && pUbersaw) { if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber()) { pMedigun->AddCharge(); } } CWeaponKritzkrieg *pKritzkrieg = static_cast<CWeaponKritzkrieg*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_KRITZKRIEG)); if (pKritzkrieg && pUbersaw) { if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber()) { pKritzkrieg->AddCharge(); } } CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDmgType, iCustomDamage ); CalculateMeleeDamageForce( &info, vecForward, vecSwingEnd, 1.0f / flDamage * tf_meleeattackforcescale.GetFloat() ); trace.m_pEnt->DispatchTraceAttack( info, vecForward, &trace ); ApplyMultiDamage(); OnEntityHit( trace.m_pEnt ); #endif // Don't impact trace friendly players or objects if ( trace.m_pEnt && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber() ) { #ifdef CLIENT_DLL UTIL_ImpactTrace( &trace, DMG_CLUB ); #endif m_bConnected = true; } } #if !defined (CLIENT_DLL) lagcompensation->FinishLagCompensation( pPlayer ); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFFlameThrower::SecondaryAttack() { if ( !tf2c_airblast.GetBool() ) return; int iNoAirblast = 0; CALL_ATTRIB_HOOK_FLOAT( iNoAirblast, set_flamethrower_push_disabled ); if ( iNoAirblast ) return; // Get the player owning the weapon. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); if ( !pOwner ) return; if ( !CanAttack() ) { m_iWeaponState = FT_STATE_IDLE; return; } #ifdef CLIENT_DLL StopFlame(); #endif m_iWeaponState = FT_STATE_AIRBLASTING; SendWeaponAnim( ACT_VM_SECONDARYATTACK ); WeaponSound( WPN_DOUBLE ); #ifdef CLIENT_DLL if ( prediction->IsFirstTimePredicted() ) { StartFlame(); } #else // Let the player remember the usercmd he fired a weapon on. Assists in making decisions about lag compensation. pOwner->NoteWeaponFired(); pOwner->SpeakWeaponFire(); CTF_GameStats.Event_PlayerFiredWeapon( pOwner, false ); // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pOwner, pOwner->GetCurrentCommand() ); Vector vecDir; QAngle angDir = pOwner->EyeAngles(); AngleVectors( angDir, &vecDir ); const Vector vecBlastSize = Vector( 128, 128, 64 ); // Picking max out of length, width, height for airblast distance. float flBlastDist = max( max( vecBlastSize.x, vecBlastSize.y ), vecBlastSize.z ); Vector vecOrigin = pOwner->Weapon_ShootPosition() + vecDir * flBlastDist; CBaseEntity *pList[64]; int count = UTIL_EntitiesInBox( pList, 64, vecOrigin - vecBlastSize, vecOrigin + vecBlastSize, 0 ); if ( tf2c_debug_airblast.GetBool() ) { NDebugOverlay::Box( vecOrigin, -vecBlastSize, vecBlastSize, 0, 0, 255, 100, 2.0 ); } for ( int i = 0; i < count; i++ ) { CBaseEntity *pEntity = pList[i]; if ( !pEntity ) continue; if ( pEntity == pOwner ) continue; if ( !pEntity->IsDeflectable() ) continue; // Make sure we can actually see this entity so we don't hit anything through walls. trace_t tr; UTIL_TraceLine( pOwner->Weapon_ShootPosition(), pEntity->WorldSpaceCenter(), MASK_SOLID, this, COLLISION_GROUP_DEBRIS, &tr ); if ( tr.fraction != 1.0f ) continue; if ( pEntity->IsPlayer() ) { if ( !pEntity->IsAlive() ) continue; CTFPlayer *pTFPlayer = ToTFPlayer( pEntity ); Vector vecPushDir; QAngle angPushDir = angDir; // Push them at least 45 degrees up. angPushDir[PITCH] = min( -45, angPushDir[PITCH] ); AngleVectors( angPushDir, &vecPushDir ); DeflectPlayer( pTFPlayer, pOwner, vecPushDir ); } else { // Deflect projectile to the point that we're aiming at, similar to rockets. Vector vecPos = pEntity->GetAbsOrigin(); Vector vecDeflect; GetProjectileReflectSetup( GetTFPlayerOwner(), vecPos, &vecDeflect, false ); DeflectEntity( pEntity, pOwner, vecDeflect ); } } lagcompensation->FinishLagCompensation( pOwner ); #endif float flAmmoPerSecondaryAttack = TF_FLAMETHROWER_AMMO_PER_SECONDARY_ATTACK; CALL_ATTRIB_HOOK_FLOAT( flAmmoPerSecondaryAttack, mult_airblast_cost ); pOwner->RemoveAmmo( flAmmoPerSecondaryAttack, m_iPrimaryAmmoType ); // Don't allow firing immediately after airblasting. m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.75f; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponMedigun::ManageChargeEffect( void ) { C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); C_BaseEntity *pEffectOwner = this; if ( pLocalPlayer == NULL ) return; if ( pLocalPlayer == GetTFPlayerOwner() ) { pEffectOwner = pLocalPlayer->GetViewModel(); if ( !pEffectOwner ) return; } bool bOwnerTaunting = false; if ( GetTFPlayerOwner() && GetTFPlayerOwner()->m_Shared.InCond( TF_COND_TAUNTING ) == true ) { bOwnerTaunting = true; } if ( GetTFPlayerOwner() && bOwnerTaunting == false && m_bHolstered == false && ( m_flChargeLevel >= 1.0f || m_bChargeRelease == true ) ) { if ( m_pChargeEffect == NULL ) { char *pszEffectName = NULL; switch( GetTFPlayerOwner()->GetTeamNumber() ) { case TF_TEAM_BLUE: pszEffectName = "medicgun_invulnstatus_fullcharge_blue"; break; case TF_TEAM_RED: pszEffectName = "medicgun_invulnstatus_fullcharge_red"; break; case TF_TEAM_GREEN: pszEffectName = "medicgun_invulnstatus_fullcharge_green"; break; case TF_TEAM_YELLOW: pszEffectName = "medicgun_invulnstatus_fullcharge_yellow"; break; default: pszEffectName = ""; break; } m_pChargeEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" ); } if ( m_pChargedSound == NULL ) { CLocalPlayerFilter filter; CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); m_pChargedSound = controller.SoundCreate( filter, entindex(), "WeaponMedigun.Charged" ); controller.Play( m_pChargedSound, 1.0, 100 ); } } else { if ( m_pChargeEffect != NULL ) { pEffectOwner->ParticleProp()->StopEmission( m_pChargeEffect ); m_pChargeEffect = NULL; } if ( m_pChargedSound != NULL ) { CSoundEnvelopeController::GetController().SoundDestroy( m_pChargedSound ); m_pChargedSound = NULL; } } }