//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #ifdef CLIENT_DLL #include "c_sdk_player.h" #else #include "sdk_player.h" #endif #include "gamevars_shared.h" #include "takedamageinfo.h" #include "effect_dispatch_data.h" #include "engine/ivdebugoverlay.h" ConVar sv_showimpacts("sv_showimpacts", "0", FCVAR_REPLICATED, "Shows client (red) and server (blue) bullet impact point" ); void DispatchEffect( const char *pName, const CEffectData &data ); CWeaponSDKBase* CSDKPlayer::SDKAnim_GetActiveWeapon() { return GetActiveSDKWeapon(); } bool CSDKPlayer::SDKAnim_CanMove() { return true; } void CSDKPlayer::FireBullet( Vector vecSrc, // shooting postion const QAngle &shootAngles, //shooting angle float vecSpread, // spread vector int iDamage, // base damage int iBulletType, // ammo type CBaseEntity *pevAttacker, // shooter bool bDoEffects, // create impact effect ? float x, // spread x factor float y // spread y factor ) { float fCurrentDamage = iDamage; // damage of the bullet at it's current trajectory float flCurrentDistance = 0.0; //distance that the bullet has traveled so far Vector vecDirShooting, vecRight, vecUp; AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp ); if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves // add the spray Vector vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; VectorNormalize( vecDir ); float flMaxRange = 8000; Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units trace_t tr; // main enter bullet trace UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1.0f ) return; // we didn't hit anything, stop tracing shoot if ( sv_showimpacts.GetBool() ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 4, true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( 4, true ); } #endif } //calculate the damage based on the distance the bullet travelled. flCurrentDistance += tr.fraction * flMaxRange; // damage get weaker of distance fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500)); int iDamageType = DMG_BULLET | DMG_NEVERGIB; if( bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { trace_t waterTrace; UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) { data.m_fFlags |= FX_WATER_IN_SLIME; } DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; if ( !( !friendlyfire.GetBool() && pEntity && pEntity->IsPlayer() && pEntity->GetTeamNumber() == GetTeamNumber() ) ) { UTIL_ImpactTrace( &tr, iDamageType ); } } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL ClearMultiDamage(); CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType ); CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr ); TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir ); ApplyMultiDamage(); #endif }