//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponAR2::SecondaryAttack( void ) { if ( m_bShotDelayed ) return; // Cannot fire underwater if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } m_bShotDelayed = true; m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flDelayedFire = gpGlobals->curtime + 0.5f; CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if( pPlayer ) { pPlayer->RumbleEffect(RUMBLE_AR2_ALT_FIRE, 0, RUMBLE_FLAG_RESTART ); } // turn off ironsights DisableIronsights(); SendWeaponAnim( ACT_VM_FIDGET ); WeaponSound( SPECIAL1 ); m_iSecondaryAttacks++; gamestats->Event_WeaponFired( pPlayer, false, GetClassname() ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::SecondaryAttack( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; //Must have ammo if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } if( m_bInReload ) m_bInReload = false; // MUST call sound before removing a round from the clip of a CMachineGun BaseClass::WeaponSound( WPN_DOUBLE ); DisableIronsights(); pPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAGS_NONE ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow; // Don't autoaim on grenade tosses AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); VectorScale( vecThrow, 1000.0f, vecThrow ); //Create the grenade QAngle angles; VectorAngles( vecThrow, angles ); CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, angles, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); pGrenade->SetThrower( GetOwner() ); pGrenade->SetDamage( sk_plr_dmg_smg1_grenade.GetFloat() ); SendWeaponAnim( ACT_VM_SECONDARYATTACK ); CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // Decrease ammo pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); // Can shoot again immediately m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; // Register a muzzleflash for the AI. pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); m_iSecondaryAttacks++; gamestats->Event_WeaponFired( pPlayer, false, GetClassname() ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponAR2::DelayedAttack( void ) { m_bShotDelayed = false; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; // turn off ironsights DisableIronsights(); // Deplete the clip completely SendWeaponAnim( ACT_VM_SECONDARYATTACK ); m_flNextSecondaryAttack = pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); // Register a muzzleflash for the AI pOwner->DoMuzzleFlash(); pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); WeaponSound( WPN_DOUBLE ); pOwner->RumbleEffect(RUMBLE_SHOTGUN_DOUBLE, 0, RUMBLE_FLAG_RESTART ); // Fire the bullets Vector vecSrc = pOwner->Weapon_ShootPosition( ); Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); // Fire the bullets Vector vecVelocity = vecAiming * 1000.0f; // Fire the combine ball CreateCombineBall( vecSrc, vecVelocity, sk_weapon_ar2_alt_fire_radius.GetFloat(), sk_weapon_ar2_alt_fire_mass.GetFloat(), sk_weapon_ar2_alt_fire_duration.GetFloat(), pOwner ); // View effects color32 white = {255, 255, 255, 64}; UTIL_ScreenFade( pOwner, white, 0.1, 0, FFADE_IN ); //Disorient the player QAngle angles = pOwner->GetLocalAngles(); angles.x += random->RandomInt( -4, 4 ); angles.y += random->RandomInt( -4, 4 ); angles.z = 0; pOwner->SnapEyeAngles( angles ); pOwner->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( 1, 2 ), 0 ) ); // Decrease ammo pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); // Can shoot again immediately m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; }
//----------------------------------------------------------------------------- // Purpose: Override so shotgun can do mulitple reloads in a row //----------------------------------------------------------------------------- void CWeaponShotgun::ItemPostFrame( void ) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if (!pOwner) { return; } //Create our trace_t class to hold the end result trace_t WallTR; //Create Vectors for the start, stop, and direction Vector vecAbsStart, vecAbsEnd, vecDir; //Take the Player's EyeAngles and turn it into a direction AngleVectors( pOwner->EyeAngles(), &vecDir ); //Get the Start/End vecAbsStart = pOwner->EyePosition(); vecAbsEnd = vecAbsStart + (vecDir * 32.0); //Do the TraceLine, and write our results to our trace_t class, tr. UTIL_TraceLine( vecAbsStart, vecAbsEnd, MASK_ALL, pOwner, COLLISION_GROUP_NONE, &WallTR ); if (WallTR.DidHit()) { bLowered = true; SendWeaponAnim( ACT_VM_IDLE_LOWERED ); m_fLoweredReady = gpGlobals->curtime + GetViewModelSequenceDuration(); m_flNextPrimaryAttack = m_fLoweredReady; } else if ( !bLowered && (pOwner->m_nButtons & IN_SPEED ) ) { bLowered = true; SendWeaponAnim( ACT_VM_IDLE_LOWERED ); m_fLoweredReady = gpGlobals->curtime + GetViewModelSequenceDuration(); m_flNextPrimaryAttack = m_fLoweredReady; } else if ( bLowered && !(pOwner->m_nButtons & IN_SPEED ) ) { bLowered = false; SendWeaponAnim( ACT_VM_IDLE ); m_fLoweredReady = gpGlobals->curtime + GetViewModelSequenceDuration(); m_flNextPrimaryAttack = m_fLoweredReady; } if ( pOwner->m_nButtons & IN_ALT1 && !bLowered ) { // reload when reload is pressed, or if no buttons are down and weapon is empty. EnableIronsights(); } else if ( !( pOwner->m_nButtons & IN_ALT1) || bLowered ) { DisableIronsights(); } if ( bLowered ) { if ( gpGlobals->curtime > m_fLoweredReady ) { bLowered = true; SendWeaponAnim( ACT_VM_IDLE_LOWERED ); m_fLoweredReady = gpGlobals->curtime + GetViewModelSequenceDuration(); } return; } else if ( bLowered ) { if ( gpGlobals->curtime > m_fLoweredReady ) { bLowered = false; SendWeaponAnim( ACT_VM_IDLE ); m_fLoweredReady = gpGlobals->curtime + GetViewModelSequenceDuration(); } return; } if (m_bInReload) { // If I'm primary firing and have one round stop reloading and fire if ((pOwner->m_nButtons & IN_ATTACK ) && (m_iClip1 >=1)) { m_bInReload = false; m_bNeedPump = false; m_bDelayedFire1 = true; } // If I'm secondary firing and have one round stop reloading and fire else if ((pOwner->m_nButtons & IN_ATTACK2 ) && (m_iClip1 >=2)) { m_bInReload = false; m_bNeedPump = false; m_bDelayedFire2 = true; } else if (m_flNextPrimaryAttack <= gpGlobals->curtime) { // If out of ammo end reload if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <=0) { FinishReload(); return; } // If clip not full reload again if (m_iClip1 < GetMaxClip1()) { Reload(); return; } // Clip full, stop reloading else { FinishReload(); return; } } } else { // Make shotgun shell invisible SetBodygroup(1,1); } if ((m_bNeedPump) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) { Pump(); return; } // Shotgun uses same timing and ammo for secondary attack if ((m_bDelayedFire2 || pOwner->m_nButtons & IN_ATTACK2)&&(m_flNextPrimaryAttack <= gpGlobals->curtime)) { m_bDelayedFire2 = false; if ( (m_iClip1 <= 1 && UsesClipsForAmmo1())) { // If only one shell is left, do a single shot instead if ( m_iClip1 == 1 ) { PrimaryAttack(); } else if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) { DryFire(); } else { StartReload(); } } // Fire underwater? else if (GetOwner()->GetWaterLevel() == 3 && m_bFiresUnderwater == false) { WeaponSound(EMPTY); m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; return; } else { // If the firing button was just pressed, reset the firing time if ( pOwner->m_afButtonPressed & IN_ATTACK ) { m_flNextPrimaryAttack = gpGlobals->curtime; } SecondaryAttack(); } } else if ( (m_bDelayedFire1 || pOwner->m_nButtons & IN_ATTACK) && m_flNextPrimaryAttack <= gpGlobals->curtime) { m_bDelayedFire1 = false; if ( (m_iClip1 <= 0 && UsesClipsForAmmo1()) || ( !UsesClipsForAmmo1() && !pOwner->GetAmmoCount(m_iPrimaryAmmoType) ) ) { if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) { DryFire(); } else { StartReload(); } } // Fire underwater? else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false) { WeaponSound(EMPTY); m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; return; } else { // If the firing button was just pressed, reset the firing time CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer && pPlayer->m_afButtonPressed & IN_ATTACK ) { m_flNextPrimaryAttack = gpGlobals->curtime; } PrimaryAttack(); } } if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) { // reload when reload is pressed, or if no buttons are down and weapon is empty. StartReload(); } else { // no fire buttons down m_bFireOnEmpty = false; if ( !HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime ) { // weapon isn't useable, switch. if ( !(GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && pOwner->SwitchToNextBestWeapon( this ) ) { m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; return; } } else { // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing if ( m_iClip1 <= 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime ) { if (StartReload()) { // if we've successfully started to reload, we're done return; } } } WeaponIdle( ); return; } }