//----------------------------------------------------------------------------- // 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 ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow; // Don't autoaim on grenade tosses AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); VectorScale( vecThrow, 1000.0f, vecThrow ); #ifndef CLIENT_DLL //Create the grenade CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); pGrenade->SetThrower( GetOwner() ); pGrenade->SetDamage( SMG1_GRENADE_DAMAGE ); pGrenade->SetDamageRadius( SMG1_GRENADE_RADIUS ); CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); // Register a muzzleflash for the AI. pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); #endif SendWeaponAnim( ACT_VM_SECONDARYATTACK ); // 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; }
//----------------------------------------------------------------------------- // 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 ); 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 ); // 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 ); }
//----------------------------------------------------------------------------- // 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 ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } // MUST call sound before removing a round from the clip of a CMachineGun BaseClass::WeaponSound( DOUBLE ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ) * 1000.0f; //Create the grenade CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY ); pGrenade->SetOwner( GetOwner() ); pGrenade->SetDamage( sk_plr_dmg_ar2_grenade.GetFloat() ); SendWeaponAnim( ACT_VM_SECONDARYATTACK ); // 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 ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_SMG1: { Vector vecShootOrigin, vecShootDir; QAngle angDiscard; // Support old style attachment point firing if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard))) { vecShootOrigin = pOperator->Weapon_ShootPosition(); } CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT( npc != NULL ); vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); } break; case EVENT_WEAPON_AR2_ALTFIRE: { CAI_BaseNPC *npc = pOperator->MyNPCPointer(); Vector vecShootOrigin, vecShootDir; vecShootOrigin = pOperator->Weapon_ShootPosition(); //vecShootDir = npc->GetShootEnemyDir( vecShootOrigin ); //Checks if it can fire the grenade WeaponRangeAttack2Condition(); Vector vecThrow = m_vecTossVelocity; //If on the rare case the vector is 0 0 0, cancel for avoid launching the grenade without speed //This should be on WeaponRangeAttack2Condition(), but for some unknown reason return CASE_NONE //doesn't stop the launch if (vecThrow == Vector(0, 0, 0)) { break; } CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create("grenade_ar2", vecShootOrigin, vec3_angle, npc); pGrenade->SetAbsVelocity(vecThrow); pGrenade->SetLocalAngularVelocity(RandomAngle(-400, 400)); //tumble in air pGrenade->SetMoveType(MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE); pGrenade->SetThrower(GetOwner()); pGrenade->SetGravity(0.5); // lower gravity since grenade is aerodynamic and engine doesn't know it. pGrenade->SetDamage(sk_plr_dmg_smg1_grenade.GetFloat()); if (g_pGameRules->IsSkillLevel(SKILL_HARD)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(2,3); } else if (g_pGameRules->IsSkillLevel(SKILL_VERYHARD)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(1.5,2); } else if (g_pGameRules->IsSkillLevel(SKILL_NIGHTMARE)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(1,1.5); } else { m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown. } m_iClip2--; } break; default: BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); break; } }