summaryrefslogtreecommitdiff
path: root/game/shared/cstrike/fx_cs_shared.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/cstrike/fx_cs_shared.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/cstrike/fx_cs_shared.cpp')
-rw-r--r--game/shared/cstrike/fx_cs_shared.cpp345
1 files changed, 345 insertions, 0 deletions
diff --git a/game/shared/cstrike/fx_cs_shared.cpp b/game/shared/cstrike/fx_cs_shared.cpp
new file mode 100644
index 0000000..446d2b5
--- /dev/null
+++ b/game/shared/cstrike/fx_cs_shared.cpp
@@ -0,0 +1,345 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "fx_cs_shared.h"
+#include "weapon_csbase.h"
+
+#ifndef CLIENT_DLL
+ #include "ilagcompensationmanager.h"
+#endif
+
+ConVar weapon_accuracy_logging( "weapon_accuracy_logging", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY | FCVAR_ARCHIVE );
+
+#ifdef CLIENT_DLL
+
+#include "fx_impact.h"
+
+ // this is a cheap ripoff from CBaseCombatWeapon::WeaponSound():
+ void FX_WeaponSound(
+ int iPlayerIndex,
+ WeaponSound_t sound_type,
+ const Vector &vOrigin,
+ CCSWeaponInfo *pWeaponInfo, float flSoundTime )
+ {
+
+ // If we have some sounds from the weapon classname.txt file, play a random one of them
+ const char *shootsound = pWeaponInfo->aShootSounds[ sound_type ];
+ if ( !shootsound || !shootsound[0] )
+ return;
+
+ CBroadcastRecipientFilter filter; // this is client side only
+ if ( !te->CanPredict() )
+ return;
+
+ CBaseEntity::EmitSound( filter, iPlayerIndex, shootsound, &vOrigin, flSoundTime );
+ }
+
+ class CGroupedSound
+ {
+ public:
+ string_t m_SoundName;
+ Vector m_vPos;
+ };
+
+ CUtlVector<CGroupedSound> g_GroupedSounds;
+
+
+ // Called by the ImpactSound function.
+ void ShotgunImpactSoundGroup( const char *pSoundName, const Vector &vEndPos )
+ {
+ int i;
+ // Don't play the sound if it's too close to another impact sound.
+ for ( i=0; i < g_GroupedSounds.Count(); i++ )
+ {
+ CGroupedSound *pSound = &g_GroupedSounds[i];
+
+ if ( vEndPos.DistToSqr( pSound->m_vPos ) < 300*300 )
+ {
+ if ( Q_stricmp( pSound->m_SoundName, pSoundName ) == 0 )
+ return;
+ }
+ }
+
+ // Ok, play the sound and add it to the list.
+ CLocalPlayerFilter filter;
+ C_BaseEntity::EmitSound( filter, NULL, pSoundName, &vEndPos );
+
+ i = g_GroupedSounds.AddToTail();
+ g_GroupedSounds[i].m_SoundName = pSoundName;
+ g_GroupedSounds[i].m_vPos = vEndPos;
+ }
+
+
+ void StartGroupingSounds()
+ {
+ Assert( g_GroupedSounds.Count() == 0 );
+ SetImpactSoundRoute( ShotgunImpactSoundGroup );
+ }
+
+
+ void EndGroupingSounds()
+ {
+ g_GroupedSounds.Purge();
+ SetImpactSoundRoute( NULL );
+ }
+
+#else
+
+ #include "te_shotgun_shot.h"
+
+ // Server doesn't play sounds anyway.
+ void StartGroupingSounds() {}
+ void EndGroupingSounds() {}
+ void FX_WeaponSound ( int iPlayerIndex,
+ WeaponSound_t sound_type,
+ const Vector &vOrigin,
+ CCSWeaponInfo *pWeaponInfo, float flSoundTime ) {};
+
+#endif
+
+
+// This runs on both the client and the server.
+// On the server, it only does the damage calculations.
+// On the client, it does all the effects.
+void FX_FireBullets(
+ int iPlayerIndex,
+ const Vector &vOrigin,
+ const QAngle &vAngles,
+ int iWeaponID,
+ int iMode,
+ int iSeed,
+ float fInaccuracy,
+ float fSpread,
+ float flSoundTime
+ )
+{
+ bool bDoEffects = true;
+
+#ifdef CLIENT_DLL
+ C_CSPlayer *pPlayer = ToCSPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) );
+#else
+ CCSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( iPlayerIndex) );
+#endif
+
+ const char * weaponAlias = WeaponIDToAlias( iWeaponID );
+
+ if ( !weaponAlias )
+ {
+ DevMsg("FX_FireBullets: weapon alias for ID %i not found\n", iWeaponID );
+ return;
+ }
+
+#if !defined(CLIENT_DLL)
+ if ( weapon_accuracy_logging.GetBool() )
+ {
+ char szFlags[256];
+
+ V_strcpy(szFlags, " ");
+
+// #if defined(CLIENT_DLL)
+// V_strcat(szFlags, "CLIENT ", sizeof(szFlags));
+// #else
+// V_strcat(szFlags, "SERVER ", sizeof(szFlags));
+// #endif
+//
+ if ( pPlayer->GetMoveType() == MOVETYPE_LADDER )
+ V_strcat(szFlags, "LADDER ", sizeof(szFlags));
+
+ if ( FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
+ V_strcat(szFlags, "GROUND ", sizeof(szFlags));
+
+ if ( FBitSet( pPlayer->GetFlags(), FL_DUCKING) )
+ V_strcat(szFlags, "DUCKING ", sizeof(szFlags));
+
+ float fVelocity = pPlayer->GetAbsVelocity().Length2D();
+
+ Msg("FireBullets @ %10f [ %s ]: inaccuracy=%f spread=%f max dispersion=%f mode=%2i vel=%10f seed=%3i %s\n",
+ gpGlobals->curtime, weaponAlias, fInaccuracy, fSpread, fInaccuracy + fSpread, iMode, fVelocity, iSeed, szFlags);
+ }
+#endif
+
+ char wpnName[128];
+ Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", weaponAlias );
+ WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName );
+
+ if ( hWpnInfo == GetInvalidWeaponInfoHandle() )
+ {
+ DevMsg("FX_FireBullets: LookupWeaponInfoSlot failed for weapon %s\n", wpnName );
+ return;
+ }
+
+ CCSWeaponInfo *pWeaponInfo = static_cast< CCSWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) );
+
+ // Do the firing animation event.
+ if ( pPlayer && !pPlayer->IsDormant() )
+ {
+ if ( iMode == Primary_Mode )
+ pPlayer->GetPlayerAnimState()->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
+ else
+ pPlayer->GetPlayerAnimState()->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_SECONDARY );
+ }
+
+#ifndef CLIENT_DLL
+ // if this is server code, send the effect over to client as temp entity
+ // Dispatch one message for all the bullet impacts and sounds.
+ TE_FireBullets(
+ iPlayerIndex,
+ vOrigin,
+ vAngles,
+ iWeaponID,
+ iMode,
+ iSeed,
+ fInaccuracy,
+ fSpread
+ );
+
+
+ // Let the player remember the usercmd he fired a weapon on. Assists in making decisions about lag compensation.
+ pPlayer->NoteWeaponFired();
+
+ bDoEffects = false; // no effects on server
+#endif
+
+ iSeed++;
+
+ int iDamage = pWeaponInfo->m_iDamage;
+ float flRange = pWeaponInfo->m_flRange;
+ int iPenetration = pWeaponInfo->m_iPenetration;
+ float flRangeModifier = pWeaponInfo->m_flRangeModifier;
+ int iAmmoType = pWeaponInfo->iAmmoType;
+
+ WeaponSound_t sound_type = SINGLE;
+
+ // CS HACK, tweak some weapon values based on primary/secondary mode
+
+ if ( iWeaponID == WEAPON_GLOCK )
+ {
+ if ( iMode == Secondary_Mode )
+ {
+ iDamage = 18; // reduced power for burst shots
+ flRangeModifier = 0.9f;
+ }
+ }
+ else if ( iWeaponID == WEAPON_M4A1 )
+ {
+ if ( iMode == Secondary_Mode )
+ {
+ flRangeModifier = 0.95f; // slower bullets in silenced mode
+ sound_type = SPECIAL1;
+ }
+ }
+ else if ( iWeaponID == WEAPON_USP )
+ {
+ if ( iMode == Secondary_Mode )
+ {
+ iDamage = 30; // reduced damage in silenced mode
+ sound_type = SPECIAL1;
+ }
+ }
+
+ if ( bDoEffects)
+ {
+ FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo, flSoundTime );
+ }
+
+
+ // Fire bullets, calculate impacts & effects
+
+ if ( !pPlayer )
+ return;
+
+ StartGroupingSounds();
+
+#ifdef GAME_DLL
+ pPlayer->StartNewBulletGroup();
+#endif
+
+#if !defined (CLIENT_DLL)
+ // Move other players back to history positions based on local player's lag
+ lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
+#endif
+
+ RandomSeed( iSeed ); // init random system with this seed
+
+ // Get accuracy displacement
+ float fTheta0 = RandomFloat(0.0f, 2.0f * M_PI);
+ float fRadius0 = RandomFloat(0.0f, fInaccuracy);
+ float x0 = fRadius0 * cosf(fTheta0);
+ float y0 = fRadius0 * sinf(fTheta0);
+
+ const int kMaxBullets = 16;
+ float x1[kMaxBullets], y1[kMaxBullets];
+ Assert(pWeaponInfo->m_iBullets <= kMaxBullets);
+
+ // the RNG can be desynchronized by FireBullet(), so pre-generate all spread offsets
+ for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ )
+ {
+ float fTheta1 = RandomFloat(0.0f, 2.0f * M_PI);
+ float fRadius1 = RandomFloat(0.0f, fSpread);
+ x1[iBullet] = fRadius1 * cosf(fTheta1);
+ y1[iBullet] = fRadius1 * sinf(fTheta1);
+ }
+
+ for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ )
+ {
+ pPlayer->FireBullet(
+ vOrigin,
+ vAngles,
+ flRange,
+ iPenetration,
+ iAmmoType,
+ iDamage,
+ flRangeModifier,
+ pPlayer,
+ bDoEffects,
+ x0 + x1[iBullet], y0 + y1[iBullet] );
+ }
+
+#if !defined (CLIENT_DLL)
+ lagcompensation->FinishLagCompensation( pPlayer );
+#endif
+
+ EndGroupingSounds();
+}
+
+// This runs on both the client and the server.
+// On the server, it dispatches a TE_PlantBomb to visible clients.
+// On the client, it plays the planting animation.
+void FX_PlantBomb( int iPlayerIndex, const Vector &vOrigin, PlantBombOption_t option )
+{
+#ifdef CLIENT_DLL
+ C_CSPlayer *pPlayer = ToCSPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) );
+#else
+ CCSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( iPlayerIndex) );
+#endif
+
+ // Do the firing animation event.
+ if ( pPlayer && !pPlayer->IsDormant() )
+ {
+ switch ( option )
+ {
+ case PLANTBOMB_PLANT:
+ {
+ pPlayer->GetPlayerAnimState()->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
+ }
+ break;
+
+ case PLANTBOMB_ABORT:
+ {
+ pPlayer->GetPlayerAnimState()->DoAnimationEvent( PLAYERANIMEVENT_CLEAR_FIRING );
+ }
+ break;
+ }
+ }
+
+#ifndef CLIENT_DLL
+ // if this is server code, send the effect over to client as temp entity
+ // Dispatch one message for all the bullet impacts and sounds.
+ TE_PlantBomb( iPlayerIndex, vOrigin, option );
+#endif
+}
+