bool CTFWeaponBaseMelee::DoSwingTrace( trace_t &trace ) { // Setup a volume for the melee weapon to be swung - approx size, so all melee behave the same. static Vector vecSwingMins( -18, -18, -18 ); static Vector vecSwingMaxs( 18, 18, 18 ); // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return false; // Setup the swing range. Vector vecForward; AngleVectors( pPlayer->EyeAngles(), &vecForward ); Vector vecSwingStart = pPlayer->Weapon_ShootPosition(); Vector vecSwingEnd = vecSwingStart + vecForward * 48; // See if we hit anything. UTIL_TraceLine( vecSwingStart, vecSwingEnd, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction >= 1.0 ) { UTIL_TraceHull( vecSwingStart, vecSwingEnd, vecSwingMins, vecSwingMaxs, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = trace.m_pEnt; if ( !pHit || pHit->IsBSPModel() ) { // Why duck hull min/max? FindHullIntersection( vecSwingStart, trace, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer ); } // This is the point on the actual surface (the hull could have hit space) vecSwingEnd = trace.endpos; } } return ( trace.fraction < 1.0f ); }
int CCrowbar::Swing( int fFirst ) { int fDidHit = FALSE; TraceResult tr; UTIL_MakeVectors (m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecEnd = vecSrc + gpGlobals->v_forward * 32; UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr ); #ifndef CLIENT_DLL if ( tr.flFraction >= 1.0 ) { UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr ); if ( tr.flFraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit ); if ( !pHit || pHit->IsBSPModel() ) FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() ); vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space) } } #endif PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0.0, 0, 0.0 ); if ( tr.flFraction >= 1.0 ) { if (fFirst) { // miss m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); } } else { switch( ((m_iSwing++) % 2) + 1 ) { case 0: SendWeaponAnim( CROWBAR_ATTACK1HIT ); break; case 1: SendWeaponAnim( CROWBAR_ATTACK2HIT ); break; case 2: SendWeaponAnim( CROWBAR_ATTACK3HIT ); break; } // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); #ifndef CLIENT_DLL // hit fDidHit = TRUE; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); ClearMultiDamage( ); if ( (m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) { // first swing does full damage pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB ); } else { // subsequent swings do half pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar / 2, gpGlobals->v_forward, &tr, DMG_CLUB ); } ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev ); // play thwack, smack, or dong sound float flVol = 1.0; int fHitWorld = TRUE; if (pEntity) { if ( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE ) { // play thwack or smack sound switch( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break; } m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME; if ( !pEntity->IsAlive() ) return TRUE; else flVol = 0.1; fHitWorld = FALSE; } } // play texture hit sound // UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line if (fHitWorld) { float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd-vecSrc)*2, BULLET_PLAYER_CROWBAR); if ( g_pGameRules->IsMultiplayer() ) { // override the volume here, cause we don't play texture sounds in multiplayer, // and fvolbar is going to be 0 from the above call. fvolbar = 1; } // also play crowbar strike switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 1: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; } // delay the decal a bit m_trHit = tr; } m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME; #endif m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25; SetThink( &CCrowbar::Smack ); pev->nextthink = UTIL_WeaponTimeBase() + 0.2; } return fDidHit; }
//Think function to delay the impact decal until the animation is finished playing void CWeaponDODBase::Smack() { Assert( GetPlayerOwner() ); if ( !GetPlayerOwner() ) return; CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); if ( !pPlayer ) return; // Check that we are still facing the victim Vector vForward, vRight, vUp; AngleVectors( pPlayer->EyeAngles(), &vForward, &vRight, &vUp ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecEnd = vecSrc + vForward * 48; CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE ); int iTraceMask = MASK_SOLID | CONTENTS_HITBOX | CONTENTS_DEBRIS; trace_t tr; UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &filter, &tr ); const float rayExtension = 40.0f; UTIL_ClipTraceToPlayers( vecSrc, vecEnd + vForward * rayExtension, iTraceMask, &filter, &tr ); if ( tr.fraction >= 1.0 ) { Vector head_hull_mins( -16, -16, -18 ); Vector head_hull_maxs( 16, 16, 18 ); UTIL_TraceHull( vecSrc, vecEnd, head_hull_mins, head_hull_maxs, MASK_SOLID, &filter, &tr ); if ( tr.fraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = tr.m_pEnt; if ( !pHit || pHit->IsBSPModel() ) FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer ); vecEnd = tr.endpos; // This is the point on the actual surface (the hull could have hit space) } } m_trHit = tr; if ( !m_trHit.m_pEnt || (m_trHit.surface.flags & SURF_SKY) ) return; if ( m_trHit.fraction == 1.0 ) return; CPASAttenuationFilter attenuationFilter( this ); attenuationFilter.UsePredictionRules(); if( m_trHit.m_pEnt->IsPlayer() ) { if ( m_iSmackDamageType & MELEE_DMG_STRONGATTACK ) WeaponSound( SPECIAL1 ); else WeaponSound( MELEE_HIT ); } else WeaponSound( MELEE_HIT_WORLD ); int iDamageType = DMG_CLUB | DMG_NEVERGIB; #ifndef CLIENT_DLL //if they hit the bounding box, just assume a chest hit if( m_trHit.hitgroup == HITGROUP_GENERIC ) m_trHit.hitgroup = HITGROUP_CHEST; float flDamage = (float)m_iSmackDamage; CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDamageType ); if ( m_iSmackDamageType & MELEE_DMG_SECONDARYATTACK ) info.SetDamageCustom( MELEE_DMG_SECONDARYATTACK ); float flScale = (1.0f / flDamage) * dod_meleeattackforcescale.GetFloat(); Vector vecForceDir = vForward; CalculateMeleeDamageForce( &info, vecForceDir, m_trHit.endpos, flScale ); Assert( m_trHit.m_pEnt != GetPlayerOwner() ); m_trHit.m_pEnt->DispatchTraceAttack( info, vForward, &m_trHit ); ApplyMultiDamage(); #endif // We've gotten minidumps where this happened. if ( !GetPlayerOwner() ) return; CEffectData data; data.m_vOrigin = m_trHit.endpos; data.m_vStart = m_trHit.startpos; data.m_nSurfaceProp = m_trHit.surface.surfaceProps; data.m_nHitBox = m_trHit.hitbox; #ifdef CLIENT_DLL data.m_hEntity = m_trHit.m_pEnt->GetRefEHandle(); #else data.m_nEntIndex = m_trHit.m_pEnt->entindex(); #endif CPASFilter effectfilter( data.m_vOrigin ); #ifndef CLIENT_DLL effectfilter.RemoveRecipient( GetPlayerOwner() ); #endif data.m_vAngles = GetPlayerOwner()->GetAbsAngles(); data.m_fFlags = 0x1; //IMPACT_NODECAL; data.m_nDamageType = iDamageType; bool bHitPlayer = m_trHit.m_pEnt && m_trHit.m_pEnt->IsPlayer(); // don't do any impacts if we hit a teammate and ff is off if ( bHitPlayer && m_trHit.m_pEnt->GetTeamNumber() == GetPlayerOwner()->GetTeamNumber() && !friendlyfire.GetBool() ) return; if ( bHitPlayer ) { te->DispatchEffect( effectfilter, 0.0, data.m_vOrigin, "Impact", data ); } else if ( m_iSmackDamageType & MELEE_DMG_EDGE ) { data.m_nDamageType = DMG_SLASH; te->DispatchEffect( effectfilter, 0.0, data.m_vOrigin, "KnifeSlash", data ); } }
//-------------------------------------------- // iDamageAmount - how much damage to give // iDamageType - DMG_ bits // flDmgDelay - delay between attack and the giving of damage, usually timed to animation // flAttackDelay - time until we can next attack //-------------------------------------------- CBaseEntity *CWeaponDODBase::MeleeAttack( int iDamageAmount, int iDamageType, float flDmgDelay, float flAttackDelay ) { if ( !CanAttack() ) return NULL; CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); #if !defined (CLIENT_DLL) // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); #endif Vector vForward, vRight, vUp; AngleVectors( pPlayer->EyeAngles(), &vForward, &vRight, &vUp ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecEnd = vecSrc + vForward * 48; CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE ); int iTraceMask = MASK_SOLID | CONTENTS_HITBOX | CONTENTS_DEBRIS; trace_t tr; UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &filter, &tr ); const float rayExtension = 40.0f; UTIL_ClipTraceToPlayers( vecSrc, vecEnd + vForward * rayExtension, iTraceMask, &filter, &tr ); // If the exact forward trace did not hit, try a larger swept box if ( tr.fraction >= 1.0 ) { Vector head_hull_mins( -16, -16, -18 ); Vector head_hull_maxs( 16, 16, 18 ); UTIL_TraceHull( vecSrc, vecEnd, head_hull_mins, head_hull_maxs, MASK_SOLID, &filter, &tr ); if ( tr.fraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = tr.m_pEnt; if ( !pHit || pHit->IsBSPModel() ) FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer ); vecEnd = tr.endpos; // This is the point on the actual surface (the hull could have hit space) // Make sure it is in front of us Vector vecToEnd = vecEnd - vecSrc; VectorNormalize( vecToEnd ); // if zero length, always hit if ( vecToEnd.Length() > 0 ) { float dot = DotProduct( vForward, vecToEnd ); // sanity that our hit is within range if ( abs(dot) < 0.95 ) { // fake that we actually missed tr.fraction = 1.0; } } } } WeaponSound( MELEE_MISS ); bool bDidHit = ( tr.fraction < 1.0f ); if ( bDidHit ) //if the swing hit { // delay the decal a bit m_trHit = tr; // Store the ent in an EHANDLE, just in case it goes away by the time we get into our think function. m_pTraceHitEnt = tr.m_pEnt; m_iSmackDamage = iDamageAmount; m_iSmackDamageType = iDamageType; m_flSmackTime = gpGlobals->curtime + flDmgDelay; } SendWeaponAnim( GetMeleeActivity() ); // player animation pPlayer->DoAnimationEvent( PLAYERANIMEVENT_SECONDARY_ATTACK ); m_flNextPrimaryAttack = gpGlobals->curtime + flAttackDelay; m_flNextSecondaryAttack = gpGlobals->curtime + flAttackDelay; m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); #ifndef CLIENT_DLL IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" ); if ( event ) { event->SetInt( "attacker", pPlayer->GetUserID() ); event->SetInt( "weapon", GetAltWeaponID() ); gameeventmanager->FireEvent( event ); } lagcompensation->FinishLagCompensation( pPlayer ); #endif //CLIENT_DLL return tr.m_pEnt; }
int CKnife::Stab(int fFirst) { BOOL fDidHit = FALSE; UTIL_MakeVectors(m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition(); Vector vecEnd = vecSrc + gpGlobals->v_forward * 32; TraceResult tr; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); if (tr.flFraction >= 1) { UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr); if (tr.flFraction < 1) { CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit); if (!pHit || pHit->IsBSPModel()) FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, ENT(m_pPlayer->pev)); vecEnd = tr.vecEndPos; } } if (tr.flFraction >= 1) { if (fFirst) { SendWeaponAnim(KNIFE_STABMISS, UseDecrement() != FALSE); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1; if (RANDOM_LONG(0, 1)) EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94); else EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94); m_pPlayer->SetAnimation(PLAYER_ATTACK1); } } else { fDidHit = TRUE; SendWeaponAnim(KNIFE_STABHIT, UseDecrement() != FALSE); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.1; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.1; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); m_pPlayer->SetAnimation(PLAYER_ATTACK1); float flDamage = 65.0; if (pEntity && pEntity->IsPlayer()) { Vector2D vec2LOS; Vector vecForward = gpGlobals->v_forward; UTIL_MakeVectors(m_pPlayer->pev->angles); vec2LOS = vecForward.Make2D(); vec2LOS = vec2LOS.Normalize(); if (DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()) > 0.8) flDamage *= 3.0; } UTIL_MakeVectors(m_pPlayer->pev->v_angle); ClearMultiDamage(); pEntity->TraceAttack(m_pPlayer->pev, flDamage, gpGlobals->v_forward, &tr, DMG_NEVERGIB | DMG_BULLET); ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); float flVol = 1; int fHitWorld = TRUE; if (pEntity) { if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) { EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_stab.wav", VOL_NORM, ATTN_NORM); m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME; if (!pEntity->IsAlive()) return TRUE; flVol = 0.1; fHitWorld = FALSE; } } if (fHitWorld) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR); EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hitwall1.wav", VOL_NORM, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3)); } m_trHit = tr; m_pPlayer->m_iWeaponVolume = flVol * KNIFE_WALLHIT_VOLUME; SetThink(&CKnife::Smack); pev->nextthink = UTIL_WeaponTimeBase() + 0.2; } return fDidHit; }
int CKnife::Swing(int fFirst) { BOOL fDidHit = FALSE; UTIL_MakeVectors(m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition(); Vector vecEnd = vecSrc + gpGlobals->v_forward * 48; TraceResult tr; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); if (tr.flFraction >= 1) { UTIL_TraceHull(vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT(m_pPlayer->pev), &tr); if (tr.flFraction < 1) { CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit); if (!pHit || pHit->IsBSPModel()) FindHullIntersection(vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, ENT(m_pPlayer->pev)); vecEnd = tr.vecEndPos; } } if (tr.flFraction >= 1) { if (fFirst) { if (m_pPlayer->HasShield() == false) { switch ((m_iSwing++) % 2) { case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break; case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break; } m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.35; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5; } else { SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2; } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2; if (RANDOM_LONG(0, 1)) EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_slash1.wav", VOL_NORM, ATTN_NORM, 0, 94); else EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_slash2.wav", VOL_NORM, ATTN_NORM, 0, 94); m_pPlayer->SetAnimation(PLAYER_ATTACK1); } } else { fDidHit = TRUE; if (m_pPlayer->HasShield() == false) { switch ((m_iSwing++) % 2) { case 0: SendWeaponAnim(KNIFE_MIDATTACK1HIT, UseDecrement() != FALSE); break; case 1: SendWeaponAnim(KNIFE_MIDATTACK2HIT, UseDecrement() != FALSE); break; } m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.4; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5; } else { SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2; } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); SetPlayerShieldAnim(); m_pPlayer->SetAnimation(PLAYER_ATTACK1); ClearMultiDamage(); if (m_flNextPrimaryAttack + 0.4 < UTIL_WeaponTimeBase()) pEntity->TraceAttack(m_pPlayer->pev, 20, gpGlobals->v_forward, &tr, DMG_NEVERGIB | DMG_BULLET); else pEntity->TraceAttack(m_pPlayer->pev, 15, gpGlobals->v_forward, &tr, DMG_NEVERGIB | DMG_BULLET); ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); float flVol = 1; int fHitWorld = TRUE; if (pEntity) { if (pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) { switch (RANDOM_LONG(0, 3)) { case 0: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_hit1.wav", VOL_NORM, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_hit2.wav", VOL_NORM, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_hit3.wav", VOL_NORM, ATTN_NORM); break; case 3: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/knife_hit4.wav", VOL_NORM, ATTN_NORM); break; } m_pPlayer->m_iWeaponVolume = KNIFE_BODYHIT_VOLUME; if (!pEntity->IsAlive()) return TRUE; flVol = 0.1; fHitWorld = FALSE; } } if (fHitWorld) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd - vecSrc) * 2, BULLET_PLAYER_CROWBAR); EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/knife_hitwall1.wav", VOL_NORM, ATTN_NORM, 0, 98 + RANDOM_LONG(0, 3)); } m_trHit = tr; m_pPlayer->m_iWeaponVolume = flVol * KNIFE_WALLHIT_VOLUME; SetThink(&CKnife::Smack); pev->nextthink = UTIL_WeaponTimeBase() + 0.2; SetPlayerShieldAnim(); } return fDidHit; }
void CBaseMelee::Swing() { if(m_pPlayer->pev->flags & FL_DUCKING || m_pPlayer->pev->button & IN_DUCK) return; //BP to prevent players from stabbing right after getting up if(m_fNextStabTime > UTIL_WeaponTimeBase()) return; SetWeaponDamage(pData->flSecondaryDmgModifier); TraceResult tr; UTIL_MakeVectors(m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecEnd = vecSrc + gpGlobals->v_forward * this->pData->flBladeLength; UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr ); #ifndef CLIENT_DLL CBaseEntity *pHit = NULL; if ( tr.flFraction >= 1.0 ) { UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr ); if ( tr.flFraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection pHit = CBaseEntity::Instance( tr.pHit ); if ( !pHit || pHit->IsBSPModel() ) { FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() ); } vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space) } } if(tr.flFraction < 1.0) { pHit = CBaseEntity::Instance( tr.pHit ); if (pHit && pHit->pev->takedamage) { float flDamage = m_pPlayer->GetDamage(m_pPlayer->pev, gpGlobals->v_forward, &tr); if(pHit->IsPlayer()) { Vector vecOrg = tr.vecEndPos - gpGlobals->v_forward * 4; if ( g_pGameRules->FPlayerCanTakeDamage( m_pPlayer, pHit ) && flDamage != 0.0) { ClearMultiDamage( ); pHit->TraceAttack(m_pPlayer->pev, flDamage, gpGlobals->v_forward, &tr, DMG_CLUB | DMG_NEVERGIB ); ApplyMultiDamage( pev, m_pPlayer->pev ); EMIT_SOUND(ENT(pev), CHAN_WEAPON, pData->snd_hit, 1, ATTN_NORM); SpawnBlood( vecOrg, BLOOD_COLOR_RED, flDamage * 4 ); // Make a lot of Blood! } } else { ClearMultiDamage( ); pHit->TraceAttack(m_pPlayer->pev, flDamage, gpGlobals->v_forward, &tr, DMG_CLUB | DMG_NEVERGIB ); ApplyMultiDamage( pev, m_pPlayer->pev ); } } else { if(pData->snd_hitwall) EMIT_SOUND(ENT(pev), CHAN_AUTO, pData->snd_hitwall, 1, ATTN_NORM); DecalGunshot( &tr, BULLET_BLADE ); } } #endif m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); int flags; #if defined( CLIENT_WEAPONS ) flags = FEV_NOTHOST; #else flags = 0; #endif // use event secondary so that the bayonet weapons can use there events // melee weapons can use the same event for primary and secondary PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), pData->m_usSecondaryAttack, 0.0, m_pPlayer->pev->origin, m_pPlayer->pev->angles, 0.0, 0, m_pPlayer->pev->team, m_iId, 0, 0 ); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + pData->flAttackDelay; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + pData->flAttackDelay; m_pPlayer->BurnStamina(MAX_STAMINA / 10, (float)0.1); }