void CISlave::ArmBeam(int side) { TraceResult tr; float flDist = 1.0; if(m_iBeams >= ISLAVE_MAX_BEAMS) return; UTIL_MakeAimVectors(pev->angles); Vector vecSrc = pev->origin + gpGlobals->v_up * 36 + gpGlobals->v_right * side * 16 + gpGlobals->v_forward * 32; for(int i = 0; i < 3; i++) { Vector vecAim = gpGlobals->v_right * side * RANDOM_FLOAT(0, 1) + gpGlobals->v_up * RANDOM_FLOAT(-1, 1); TraceResult tr1; UTIL_TraceLine(vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT(pev), &tr1); if(flDist > tr1.flFraction) { tr = tr1; flDist = tr.flFraction; } } // Couldn't find anything close enough if(flDist == 1.0) return; DecalGunshot(&tr, BULLET_PLAYER_CROWBAR); m_pBeam[m_iBeams] = CBeam::BeamCreate("sprites/lgtning.spr", 30); if(!m_pBeam[m_iBeams]) return; m_pBeam[m_iBeams]->PointEntInit(tr.vecEndPos, entindex()); m_pBeam[m_iBeams]->SetEndAttachment(side < 0 ? 2 : 1); // m_pBeam[m_iBeams]->SetColor( 180, 255, 96 ); m_pBeam[m_iBeams]->SetColor(96, 128, 16); m_pBeam[m_iBeams]->SetBrightness(64); m_pBeam[m_iBeams]->SetNoise(80); m_iBeams++; }
/* ================ FireBullets Go to the trouble of combining multiple pellets into a single damage call. ================ */ void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker ) { static int tracerCount; int tracer; TraceResult tr; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; if ( pevAttacker == NULL ) pevAttacker = pev; // the default attacker is ourselves // Vector vecSrc = pev->origin + gpGlobals->v_forward * 10; //vecSrc.z = pevShooter->absmin.z + pevShooter->size.z * 0.7; //vecSrc.z = pev->origin.z + (pev->view_ofs.z - 4); ClearMultiDamage(); gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; for (ULONG iShot = 1; iShot <= cShots; iShot++) { // get circular gaussian spread float x, y, z; do { x = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); y = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); z = x*x+y*y; } while (z > 1); Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; Vector vecEnd; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr); tracer = 0; if (iTracerFreq != 0 && (tracerCount++ % iTracerFreq) == 0) { Vector vecTracerSrc; if ( IsPlayer() ) {// adjust tracer position for player vecTracerSrc = vecSrc + Vector ( 0 , 0 , -4 ) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16; } else { vecTracerSrc = vecSrc; } if ( iTracerFreq != 1 ) // guns that always trace also always decal tracer = 1; switch( iBulletType ) { case BULLET_PLAYER_MP5: case BULLET_MONSTER_MP5: case BULLET_MONSTER_9MM: case BULLET_MONSTER_12MM: default: break; } } // do damage, paint decals if (tr.flFraction != 1.0) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if ( iDamage ) { pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } else switch(iBulletType) { default: case BULLET_PLAYER_9MM: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg9MM, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_BUCKSHOT: // make distance based! pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgBuckshot, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_357: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET); break; case BULLET_MONSTER_9MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); break; case BULLET_MONSTER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); break; case BULLET_MONSTER_12MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET); if ( !tracer ) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } break; case BULLET_NONE: // FIX pEntity->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0) { UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) ); } break; } } // make bullet trails UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 ); } ApplyMultiDamage(pev, pevAttacker); }
// CS Vector CBaseEntity::FireBullets3( Vector vecSrc, Vector vecDirShooting, float flSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand ) { int originalPenetration = iPenetration; int penetrationPower; float penetrationDistance; int currentDamage = iDamage; float currentDistance; TraceResult tr; TraceResult tr2; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; bool hitMetal = false; switch( iBulletType ) { case BULLET_PLAYER_9MM: { penetrationPower = 21; penetrationDistance = 800; break; } case BULLET_PLAYER_45ACP: { penetrationPower = 15; penetrationDistance = 500; break; } case BULLET_PLAYER_50AE: { penetrationPower = 30; penetrationDistance = 1000; break; } case BULLET_PLAYER_762MM: { penetrationPower = 39; penetrationDistance = 5000; break; } case BULLET_PLAYER_556MM: { penetrationPower = 35; penetrationDistance = 4000; break; } case BULLET_PLAYER_338MAG: { penetrationPower = 45; penetrationDistance = 8000; break; } case BULLET_PLAYER_57MM: { penetrationPower = 30; penetrationDistance = 2000; break; } case BULLET_PLAYER_357SIG: { penetrationPower = 25; penetrationDistance = 800; break; } default: { penetrationPower = 0; penetrationDistance = 0; break; } } if( !pevAttacker ) { pevAttacker = pev; } gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; float x, y, z; if( IsPlayer() ) { x = UTIL_SharedRandomFloat( shared_rand, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + 1, -0.5, 0.5 ); y = UTIL_SharedRandomFloat (shared_rand + 2, -0.5, 0.5 ) + UTIL_SharedRandomFloat (shared_rand + 3, -0.5, 0.5 ); } else { do { x = RANDOM_FLOAT( -0.5, 0.5 ) + RANDOM_FLOAT( -0.5, 0.5 ); y = RANDOM_FLOAT( -0.5, 0.5 ) + RANDOM_FLOAT( -0.5, 0.5 ); z = x * x + y * y; } while( z > 1 ); } Vector vecDir = vecDirShooting + x * flSpread * vecRight + y * flSpread * vecUp; Vector vecEnd = vecSrc + vecDir * flDistance; float damageModifier = 0.5; while( iPenetration ) { ClearMultiDamage(); UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr ); if( tr.flFraction != 1.0 ) { // TODO:Implement me. // TheBots->OnEvent( EVENT_BULLET_IMPACT, this, NULL ); } switch( UTIL_TextureHit( &tr, vecSrc, vecEnd ) ) { case CHAR_TEX_METAL: { hitMetal = true; penetrationPower *= 0.15; damageModifier = 0.2; break; } case CHAR_TEX_CONCRETE: { penetrationPower *= 0.25; break; } case CHAR_TEX_GRATE: { hitMetal = true; penetrationPower *= 0.5; damageModifier = 0.4; break; } case CHAR_TEX_VENT: { hitMetal = true; penetrationPower *= 0.5; damageModifier = 0.45; break; } case CHAR_TEX_TILE: { penetrationPower *= 0.65; damageModifier = 0.3; break; } case CHAR_TEX_COMPUTER: { hitMetal = true; penetrationPower *= 0.4; damageModifier = 0.45; break; } case CHAR_TEX_WOOD: { damageModifier = 0.6; break; } } if( tr.flFraction != 1.0 ) { CBaseEntity* pEntity = CBaseEntity::Instance( tr.pHit ); iPenetration--; currentDistance = tr.flFraction * flDistance; currentDamage *= pow( flRangeModifier, currentDistance / 500 ); if( currentDistance > penetrationDistance ) { iPenetration = 0; } if( tr.iHitgroup == HITGROUP_SHIELD ) { if( tr.flFraction != 1.0 ) { if( RANDOM_LONG( 0, 1 ) ) EMIT_SOUND( pEntity->edict(), CHAN_VOICE, "weapons/ric_metal-1.wav", VOL_NORM, ATTN_NORM ); else EMIT_SOUND( pEntity->edict(), CHAN_VOICE, "weapons/ric_metal-2.wav", VOL_NORM, ATTN_NORM ); UTIL_Sparks( tr.vecEndPos ); pEntity->pev->punchangle.x = currentDamage * RANDOM_FLOAT( -0.15, 0.15 ); pEntity->pev->punchangle.z = currentDamage * RANDOM_FLOAT( -0.15, 0.15 ); if( pEntity->pev->punchangle.x < 4 ) pEntity->pev->punchangle.x = 4; if( pEntity->pev->punchangle.z < -5 ) pEntity->pev->punchangle.z = -5; else if( pEntity->pev->punchangle.z > 5 ) pEntity->pev->punchangle.z = 5; } break; } float distanceModifier; if( VARS( tr.pHit )->solid != SOLID_BSP || !iPenetration ) { penetrationPower = 42.0; distanceModifier = 0.75; damageModifier = 0.75; } else { distanceModifier = 0.75; } DecalGunshot( &tr, iBulletType, bPistol || RANDOM_LONG( 0, 3 ), pev, hitMetal ); vecSrc = tr.vecEndPos + ( vecDir * penetrationPower ); flDistance = ( flDistance - currentDistance ) * distanceModifier; vecEnd = vecSrc + ( vecDir * flDistance ); pEntity->TraceAttack( pevAttacker, currentDamage, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB); currentDamage *= damageModifier; } else { iPenetration = 0; } ApplyMultiDamage( pev, pevAttacker ); } return Vector( x * flSpread, y * flSpread, 0 ); }
void CCrowbar::Smack( ) { DecalGunshot( &m_trHit, BULLET_PLAYER_CROWBAR ); }
Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand ) { static int tracerCount; TraceResult tr; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; float x, y, z; if ( pevAttacker == NULL ) pevAttacker = pev; // the default attacker is ourselves ClearMultiDamage(); gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; for ( ULONG iShot = 1; iShot <= cShots; iShot++ ) { int newDamage = iDamage; //Use player's random seed. // get circular gaussian spread x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 ); y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 ); z = x * x + y * y; Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; Vector vecEnd; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr); // do damage, paint decals if (tr.flFraction != 1.0) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); newDamage -= vec3_t( tr.vecEndPos - vecSrc ).Length() * 0.01; pEntity->TraceAttack(pevAttacker, newDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); FireBulletsWater( vecSrc, tr.vecEndPos, 0.5, 0.3 ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); if( cShots == 1 ) { float unit = iDamage; while( newDamage > 0 ) { if( POINT_CONTENTS( tr.vecEndPos + vecDir * unit ) == CONTENTS_SOLID ) break; UTIL_TraceLine(tr.vecEndPos + vecDir * unit, vecSrc, dont_ignore_monsters, ENT(pev), &tr); if( tr.fAllSolid ) break; TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); newDamage /= 2; unit /= 2; vecSrc = tr.vecEndPos; UTIL_TraceLine(tr.vecEndPos, vecEnd, dont_ignore_monsters, ENT(pev), &tr); newDamage -= vec3_t( tr.vecEndPos - vecSrc ).Length() * 0.01; pEntity = CBaseEntity::Instance(tr.pHit); pEntity->TraceAttack(pevAttacker, newDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); FireBulletsWater( vecSrc, tr.vecEndPos, 0.5, 0.3 ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } } } // make bullet trails //UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 ); } ApplyMultiDamage(pev, pevAttacker); return Vector( x * vecSpread.x, y * vecSpread.y, 0.0 ); }
/* ================ FireBullets Go to the trouble of combining multiple pellets into a single damage call. This version is used by Players, uses the random seed generator to sync client and server side shots. ================ */ Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand ) { static int tracerCount; TraceResult tr; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; float x, y, z; if ( pevAttacker == NULL ) pevAttacker = pev; // the default attacker is ourselves ClearMultiDamage(); gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; for ( ULONG iShot = 1; iShot <= cShots; iShot++ ) { //Use player's random seed. // get circular gaussian spread x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 ); y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 ); z = x * x + y * y; Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; Vector vecEnd; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr); // do damage, paint decals if (tr.flFraction != 1.0) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if ( iDamage ) { pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } else switch(iBulletType) { default: case BULLET_PLAYER_9MM: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg9MM, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_BUCKSHOT: // make distance based! pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgBuckshot, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_357: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET); break; case BULLET_NONE: // FIX pEntity->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0) { UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) ); } break; } } // make bullet trails UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 ); } ApplyMultiDamage(pev, pevAttacker); return Vector( x * vecSpread.x, y * vecSpread.y, 0.0 ); }
void CAK74::Smack( ) { DecalGunshot( &m_trHit, BULLET_PLAYER_CROWBAR ); }
/* ================ FireBullets Go to the trouble of combining multiple pellets into a single damage call. This version is used by Monsters. ================ */ void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker ) { static int tracerCount; int tracer; TraceResult tr; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; if ( pevAttacker == NULL ) pevAttacker = pev; // the default attacker is ourselves ClearMultiDamage(); gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; for (ULONG iShot = 1; iShot <= cShots; iShot++) { // get circular gaussian spread float x, y, z; do { x = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); y = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); z = x*x+y*y; } while (z > 1); Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; Vector vecEnd; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr); tracer = 0; if (iTracerFreq != 0 && (tracerCount++ % iTracerFreq) == 0) { Vector vecTracerSrc; if ( IsPlayer() ) {// adjust tracer position for player vecTracerSrc = vecSrc + Vector ( 0 , 0 , -4 ) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16; } else { vecTracerSrc = vecSrc; } if ( iTracerFreq != 1 ) // guns that always trace also always decal tracer = 1; MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecTracerSrc ); WRITE_BYTE( TE_TRACER ); WRITE_COORD( vecTracerSrc.x ); WRITE_COORD( vecTracerSrc.y ); WRITE_COORD( vecTracerSrc.z ); WRITE_COORD( tr.vecEndPos.x ); WRITE_COORD( tr.vecEndPos.y ); WRITE_COORD( tr.vecEndPos.z ); MESSAGE_END(); } // do damage, paint decals if (tr.flFraction != 1.0) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if ( iDamage ) { pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } else switch(iBulletType) { default: case BULLET_NONE: // FIX pEntity->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0) { UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) ); } break; } } // make bullet trails UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 ); } ApplyMultiDamage(pev, pevAttacker); }
// Go to the trouble of combining multiple pellets into a single damage call. // This version is used by Players, uses the random seed generator to sync client and server side shots. Vector CBaseEntity::FireBullets3(Vector vecSrc, Vector vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand) { int iOriginalPenetration = iPenetration; int iPenetrationPower; float flPenetrationDistance; int iCurrentDamage = iDamage; float flCurrentDistance; TraceResult tr, tr2; Vector vecRight, vecUp; bool bHitMetal = false; int iSparksAmount = 1; vecRight = gpGlobals->v_right; vecUp = gpGlobals->v_up; switch (iBulletType) { case BULLET_PLAYER_9MM: iPenetrationPower = 21; flPenetrationDistance = 800; break; case BULLET_PLAYER_45ACP: iPenetrationPower = 15; flPenetrationDistance = 500; break; case BULLET_PLAYER_50AE: iPenetrationPower = 30; flPenetrationDistance = 1000; break; case BULLET_PLAYER_762MM: iPenetrationPower = 39; flPenetrationDistance = 5000; break; case BULLET_PLAYER_556MM: iPenetrationPower = 35; flPenetrationDistance = 4000; break; case BULLET_PLAYER_338MAG: iPenetrationPower = 45; flPenetrationDistance = 8000; break; case BULLET_PLAYER_57MM: iPenetrationPower = 30; flPenetrationDistance = 2000; break; case BULLET_PLAYER_357SIG: iPenetrationPower = 25; flPenetrationDistance = 800; break; default: iPenetrationPower = 0; flPenetrationDistance = 0; break; } if (!pevAttacker) { // the default attacker is ourselves pevAttacker = pev; } gMultiDamage.type = (DMG_BULLET | DMG_NEVERGIB); float x, y, z; if (IsPlayer()) { // Use player's random seed. // get circular gaussian spread x = UTIL_SharedRandomFloat(shared_rand, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 1, -0.5, 0.5); y = UTIL_SharedRandomFloat(shared_rand + 2, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 3, -0.5, 0.5); } else { do { x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); z = x * x + y * y; } while (z > 1); } Vector vecDir, vecEnd; Vector vecOldSrc, vecNewSrc; vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; vecEnd = vecSrc + vecDir * flDistance; float flDamageModifier = 0.5; while (iPenetration != 0) { ClearMultiDamage(); UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr); if (TheBots != NULL && tr.flFraction != 1.0f) { TheBots->OnEvent(EVENT_BULLET_IMPACT, this, (CBaseEntity *)&tr.vecEndPos); } char cTextureType = UTIL_TextureHit(&tr, vecSrc, vecEnd); bool bSparks = false; switch (cTextureType) { case CHAR_TEX_METAL: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.15; flDamageModifier = 0.2; break; case CHAR_TEX_CONCRETE: iPenetrationPower *= 0.25; break; case CHAR_TEX_GRATE: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.5; flDamageModifier = 0.4; break; case CHAR_TEX_VENT: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.5; flDamageModifier = 0.45; break; case CHAR_TEX_TILE: iPenetrationPower *= 0.65; flDamageModifier = 0.3; break; case CHAR_TEX_COMPUTER: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.4; flDamageModifier = 0.45; break; case CHAR_TEX_WOOD: flDamageModifier = 0.6; break; default: break; } if (tr.flFraction != 1.0f) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); iPenetration--; flCurrentDistance = tr.flFraction * flDistance; iCurrentDamage *= Q_pow(flRangeModifier, flCurrentDistance / 500); if (flCurrentDistance > flPenetrationDistance) { iPenetration = 0; } if (tr.iHitgroup == HITGROUP_SHIELD) { EMIT_SOUND(pEntity->edict(), CHAN_VOICE, (RANDOM_LONG(0, 1) == 1) ? "weapons/ric_metal-1.wav" : "weapons/ric_metal-2.wav", VOL_NORM, ATTN_NORM); UTIL_Sparks(tr.vecEndPos); pEntity->pev->punchangle.x = iCurrentDamage * RANDOM_FLOAT(-0.15, 0.15); pEntity->pev->punchangle.z = iCurrentDamage * RANDOM_FLOAT(-0.15, 0.15); if (pEntity->pev->punchangle.x < 4) { pEntity->pev->punchangle.x = -4; } if (pEntity->pev->punchangle.z < -5) { pEntity->pev->punchangle.z = -5; } else if (pEntity->pev->punchangle.z > 5) { pEntity->pev->punchangle.z = 5; } break; } float flDistanceModifier; if (VARS(tr.pHit)->solid != SOLID_BSP || !iPenetration) { iPenetrationPower = 42; flDamageModifier = 0.75; flDistanceModifier = 0.75; } else flDistanceModifier = 0.5; DecalGunshot(&tr, iBulletType, (!bPistol && RANDOM_LONG(0, 3)), pev, bHitMetal); vecSrc = tr.vecEndPos + (vecDir * iPenetrationPower); flDistance = (flDistance - flCurrentDistance) * flDistanceModifier; vecEnd = vecSrc + (vecDir * flDistance); pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB)); iCurrentDamage *= flDamageModifier; } else iPenetration = 0; ApplyMultiDamage(pev, pevAttacker); } return Vector(x * vecSpread, y * vecSpread, 0); }
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker) { static int tracerCount; int tracer; TraceResult tr; Vector vecRight, vecUp; bool m_bCreatedShotgunSpark = true; vecRight = gpGlobals->v_right; vecUp = gpGlobals->v_up; if (!pevAttacker) { // the default attacker is ourselves pevAttacker = pev; } ClearMultiDamage(); gMultiDamage.type = (DMG_BULLET | DMG_NEVERGIB); for (ULONG iShot = 1; iShot <= cShots; ++iShot) { int spark = 0; // get circular gaussian spread float x, y, z; do { x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); z = x * x + y * y; } while (z > 1); Vector vecDir, vecEnd; vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr); tracer = 0; if (iTracerFreq != 0 && !(tracerCount++ % iTracerFreq)) { Vector vecTracerSrc; if (IsPlayer()) { // adjust tracer position for player vecTracerSrc = vecSrc + Vector(0, 0, -4) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16; } else { vecTracerSrc = vecSrc; } // guns that always trace also always decal if (iTracerFreq != 1) tracer = 1; MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, vecTracerSrc); WRITE_BYTE(TE_TRACER); WRITE_COORD(vecTracerSrc.x); WRITE_COORD(vecTracerSrc.y); WRITE_COORD(vecTracerSrc.z); WRITE_COORD(tr.vecEndPos.x); WRITE_COORD(tr.vecEndPos.y); WRITE_COORD(tr.vecEndPos.z); MESSAGE_END(); } // do damage, paint decals if (tr.flFraction != 1.0f) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if (iDamage) { pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB)); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); } else { float flDamage; switch (iBulletType) { case BULLET_PLAYER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_BUCKSHOT: flDamage = ((1 - tr.flFraction) * 20); pEntity->TraceAttack(pevAttacker, int(flDamage), vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_357: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET); break; case BULLET_MONSTER_9MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); break; case BULLET_MONSTER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); break; case BULLET_MONSTER_12MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET); if (!tracer) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); } break; case BULLET_NONE: flDamage = 50; pEntity->TraceAttack(pevAttacker, flDamage, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if (!FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != kRenderNormal) { UTIL_DecalTrace(&tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0, 2)); } break; default: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); break; } } } // make bullet trails UTIL_BubbleTrail(vecSrc, tr.vecEndPos, int((flDistance * tr.flFraction) / 64)); } ApplyMultiDamage(pev, pevAttacker); }
void CKnife::Smack(void) { DecalGunshot(&m_trHit, BULLET_PLAYER_CROWBAR, false, m_pPlayer->pev, false); }
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); }
/* ================ FireBullets Go to the trouble of combining multiple pellets into a single damage call. This version is used by Monsters. ================ */ void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int inDamageType) { static int tracerCount; int tracer; TraceResult tr; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; if ( pevAttacker == NULL ) pevAttacker = pev; // the default attacker is ourselves ClearMultiDamage(); gMultiDamage.type = inDamageType; for (ULONG iShot = 1; iShot <= cShots; iShot++) { // get circular gaussian spread float x, y, z; do { x = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); y = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5); z = x*x+y*y; } while (z > 1); Vector vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; Vector vecEnd; vecEnd = vecSrc + vecDir * flDistance; //UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr); bool theProtected = false; AvHSUServerTraceBullets(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), tr, theProtected); CBaseEntity* theEntityHit = CBaseEntity::Instance(tr.pHit); if(theProtected && theEntityHit) { // joev: experiment EMIT_SOUND(theEntityHit->edict(), CHAN_AUTO, kUmbraBlockedSound, 1.0f, ATTN_NORM); // :joev } else { tracer = 0; if (iTracerFreq != 0 && (tracerCount++ % iTracerFreq) == 0) { Vector vecTracerSrc; if ( IsPlayer() ) {// adjust tracer position for player vecTracerSrc = vecSrc + Vector ( 0 , 0 , -4 ) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16; } else { vecTracerSrc = vecSrc; } if ( iTracerFreq != 1 ) // guns that always trace also always decal tracer = 1; switch( iBulletType ) { case BULLET_MONSTER_MP5: case BULLET_MONSTER_9MM: case BULLET_MONSTER_12MM: default: MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecTracerSrc ); WRITE_BYTE( TE_TRACER ); WRITE_COORD( vecTracerSrc.x ); WRITE_COORD( vecTracerSrc.y ); WRITE_COORD( vecTracerSrc.z ); WRITE_COORD( tr.vecEndPos.x ); WRITE_COORD( tr.vecEndPos.y ); WRITE_COORD( tr.vecEndPos.z ); MESSAGE_END(); break; } } // do damage, paint decals if (tr.flFraction != 1.0) { float theScalar = 1.0f; if(theEntityHit && GetGameRules()->CanEntityDoDamageTo(this, theEntityHit, &theScalar)) { // Multiply damage by scalar for tourny mode, etc. iDamage *= theScalar; if ( iDamage ) { theEntityHit->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) ); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); //DecalGunshot( &tr, 0 ); } else switch(iBulletType) { default: case BULLET_MONSTER_9MM: theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); break; case BULLET_MONSTER_MP5: theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); break; case BULLET_MONSTER_12MM: theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET); if ( !tracer ) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot( &tr, iBulletType ); } break; case BULLET_NONE: // FIX theEntityHit->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0) { UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) ); } break; } } } // make bullet trails UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 ); } } ApplyMultiDamage(pev, pevAttacker); }