diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/cstrike/fx_cs_shared.cpp | |
| download | archived-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.cpp | 345 |
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 +} + |