void cRAI::DebugDrawShape(float3 centerPos, float lineLength, float width, int arrow, float yPosOffset, int lifeTime, int sides, int group) { DebugDrawLine(centerPos, lineLength, 0, -lineLength/2, lineLength/2, yPosOffset, lifeTime, arrow, width, group); DebugDrawLine(centerPos, lineLength, 1, -lineLength/2, -lineLength/2, yPosOffset, lifeTime, arrow, width, group); DebugDrawLine(centerPos, lineLength, 2, lineLength/2, -lineLength/2, yPosOffset, lifeTime, arrow, width, group); DebugDrawLine(centerPos, lineLength, 3, lineLength/2, lineLength/2, yPosOffset, lifeTime, arrow, width, group); }
void CMapzoneEdit::DrawReticle(Vector *pos, float retsize) { Vector p1, p2, p3, p4, p5, p6; p1.x = pos->x + retsize; p1.y = pos->y; p1.z = pos->z; p2.x = pos->x - retsize; p2.y = pos->y; p2.z = pos->z; p3.x = pos->x; p3.y = pos->y + retsize; p3.z = pos->z; p4.x = pos->x; p4.y = pos->y - retsize; p4.z = pos->z; p5.x = pos->x; p5.y = pos->y; p5.z = pos->z + retsize; p6.x = pos->x; p6.y = pos->y; p6.z = pos->z - retsize; DebugDrawLine(p1, p2, 255, 0, 0, true, -1.0f); DebugDrawLine(p3, p4, 255, 0, 0, true, -1.0f); DebugDrawLine(p5, p6, 255, 0, 0, true, -1.0f); }
void cRAI::DebugDrawShape(float3 CenterPos, float linelength, float width, int arrow, float yposoffset, int lifetime, int sides, int group) { DebugDrawLine(CenterPos,linelength,0,-linelength/2,linelength/2,yposoffset,lifetime,arrow,width,group); DebugDrawLine(CenterPos,linelength,1,-linelength/2,-linelength/2,yposoffset,lifetime,arrow,width,group); DebugDrawLine(CenterPos,linelength,2,linelength/2,-linelength/2,yposoffset,lifetime,arrow,width,group); DebugDrawLine(CenterPos,linelength,3,linelength/2,linelength/2,yposoffset,lifetime,arrow,width,group); }
void GraphicsWorld::DebugDrawAxes(const float3x4 &t, bool depthTest) { float3 translate, scale; Quat rotate; t.Decompose(translate, rotate, scale); DebugDrawLine(translate, translate + rotate * float3(scale.x, 0.f, 0.f), 1, 0, 0, depthTest); DebugDrawLine(translate, translate + rotate * float3(0., scale.y, 0.f), 0, 1, 0, depthTest); DebugDrawLine(translate, translate + rotate * float3(0.f, 0.f, scale.z), 0, 0, 1, depthTest); }
void GraphicsWorld::DebugDrawSphere(const float3& center, float radius, int vertices, const Color &clr, bool depthTest) { if (vertices <= 0) return; Vector<float3> positions(vertices); Sphere sphere(center, radius); int actualVertices = sphere.Triangulate(&positions[0], 0, 0, vertices, true); for (int i = 0; i < actualVertices; i += 3) { DebugDrawLine(positions[i], positions[i + 1], clr, depthTest); DebugDrawLine(positions[i + 1], positions[i + 2], clr, depthTest); DebugDrawLine(positions[i + 2], positions[i], clr, depthTest); } }
bool UTIL_ASW_BrushBlockingRoute( AI_Waypoint_t *pRoute, const int nCollisionMask, const int nCollisionGroup ) { if ( !pRoute ) return false; AI_Waypoint_t *pLastPoint = pRoute; pRoute = pRoute->GetNext(); trace_t tr; Vector vecShiftUp = Vector( 0, 0, 20 ); while ( pRoute ) { CTraceFilterSimple traceFilter( NULL, nCollisionGroup ); UTIL_TraceLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, nCollisionMask, &traceFilter, &tr ); if ( asw_blink_debug.GetBool() ) { DebugDrawLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, 255, 0, 0, true, 30.0f ); } if ( tr.DidHit() ) { return true; } pLastPoint = pRoute; pRoute = pRoute->GetNext(); } return false; }
// traces along an AI network route to see if a door is blocking the way CASW_Door* UTIL_ASW_DoorBlockingRoute( AI_Waypoint_t *pRoute, bool bRequireLockedOrSealed ) { if ( !pRoute ) return NULL; AI_Waypoint_t *pLastPoint = pRoute; pRoute = pRoute->GetNext(); trace_t tr; Vector vecShiftUp = Vector( 0, 0, 20 ); while ( pRoute ) { CASW_Trace_Filter_Doors traceFilter( NULL, COLLISION_GROUP_NONE, bRequireLockedOrSealed ); UTIL_TraceLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, MASK_NPCSOLID, &traceFilter, &tr ); if ( asw_blink_debug.GetBool() ) { DebugDrawLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, 0, 0, 255, true, 30.0f ); } if ( tr.DidHit() ) { return dynamic_cast<CASW_Door*>(tr.m_pEnt); } pLastPoint = pRoute; pRoute = pRoute->GetNext(); } return NULL; }
void GraphicsWorld::DebugDrawPlane(const Plane &plane, const Color &clr, const float3 &refPoint, float uSpacing, float vSpacing, int uSegments, int vSegments, bool depthTest) { float U0 = -uSegments * uSpacing / 2.f; float V0 = -vSegments * vSpacing / 2.f; float U1 = uSegments * uSpacing / 2.f; float V1 = vSegments * vSpacing / 2.f; for(int y = 0; y < vSegments; ++y) for(int x = 0; x < uSegments; ++x) { float u = U0 + x * uSpacing; float v = V0 + y * vSpacing; DebugDrawLine(plane.Point(U0, v, refPoint), plane.Point(U1, v, refPoint), clr, depthTest); DebugDrawLine(plane.Point(u, V0, refPoint), plane.Point(u, V1, refPoint), clr, depthTest); } }
void GraphicsWorld::DebugDrawLight(const float3x4 &t, int lightType, float range, float spotAngle, const Color &clr, bool depthTest) { float3 translate, scale; Quat rotate; t.Decompose(translate, rotate, scale); float3 lightDirection = rotate * float3(0.0f, 0.0f, 1.0f); switch (lightType) { // Point case 0: DebugDrawCircle(Circle(translate, float3(1.f, 0.f, 0.f), range), 8, clr, depthTest); DebugDrawCircle(Circle(translate, float3(0.f, 1.f, 0.f), range), 8, clr, depthTest); DebugDrawCircle(Circle(translate, float3(0.f, 0.f, 1.f), range), 8, clr, depthTest); break; // Spot case 1: { float3 endPoint = translate + range * lightDirection; float coneRadius = range * sinf(DegToRad(spotAngle)); Circle spotCircle(endPoint, -lightDirection, coneRadius); DebugDrawCircle(Circle(endPoint, -lightDirection, coneRadius), 8, clr, depthTest); for (int i = 1; i <= 8; ++i) DebugDrawLine(translate, spotCircle.GetPoint(i * 2.f * 3.14f / 8), clr, depthTest); } break; // Directional case 2: { const float cDirLightRange = 10.f; float3 endPoint = translate + cDirLightRange * lightDirection; float3 offset = rotate * float3(1.f, 0.f, 0.f); DebugDrawLine(translate, endPoint, clr, depthTest); DebugDrawLine(translate + offset, endPoint + offset, clr, depthTest); DebugDrawLine(translate - offset, endPoint - offset, clr, depthTest); } break; } }
void CASW_Path_Utils::DebugDrawRoute( const Vector &vecStartPos, AI_Waypoint_t *pWaypoint ) { Vector vecLastPos = vecStartPos; Msg(" Pathstart = %f %f %f\n", VectorExpand( g_vecPathStart ) ); while ( pWaypoint ) { Msg(" waypoint = %f %f %f\n", VectorExpand( pWaypoint->GetPos() ) ); DebugDrawLine( vecLastPos + Vector( 0, 0, 10 ) , pWaypoint->GetPos() + Vector( 0, 0, 10 ), 255, 0, 255, true, 30.0f ); vecLastPos = pWaypoint->GetPos(); pWaypoint = pWaypoint->GetNext(); } }
void ShowJointInfo(const NewtonCustomJoint* joint) { NewtonJointRecord info; if (showContacts) { joint->GetInfo (&info); dMatrix bodyMatrix0; NewtonBodyGetMatrix (info.m_attachBody_0, &bodyMatrix0[0][0]); dMatrix matrix0 (*((dMatrix*) &info.m_attachmenMatrix_0[0])); matrix0 = matrix0 * bodyMatrix0; DebugDrawLine (matrix0.m_posit, matrix0.m_posit + matrix0.m_front, dVector (1, 0, 0)); DebugDrawLine (matrix0.m_posit, matrix0.m_posit + matrix0.m_up, dVector (0, 1, 0)); DebugDrawLine (matrix0.m_posit, matrix0.m_posit + matrix0.m_right, dVector (0, 0, 1)); dMatrix bodyMatrix1; NewtonBodyGetMatrix (info.m_attachBody_1, &bodyMatrix1[0][0]); dMatrix matrix1 (*((dMatrix*) &info.m_attachmenMatrix_1[0])); matrix1 = matrix1 * bodyMatrix1; DebugDrawLine (matrix1.m_posit, matrix1.m_posit + matrix1.m_front, dVector (1, 0, 0)); DebugDrawLine (matrix1.m_posit, matrix1.m_posit + matrix1.m_up, dVector (0, 1, 0)); DebugDrawLine (matrix1.m_posit, matrix1.m_posit + matrix1.m_right, dVector (0, 0, 1)); } }
void CMapzoneEdit::Update() { if (mom_zone_edit.GetBool()) { if (!m_bEditing) { m_nBuildStage = BUILDSTAGE_NONE; m_bEditing = true; } } else { if (m_bEditing) { m_nBuildStage = BUILDSTAGE_NONE; m_bEditing = false; } return; } CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if (!pPlayer) return; trace_t tr; Vector vecFwd; AngleVectors(pPlayer->EyeAngles(), &vecFwd); UTIL_TraceLine(pPlayer->EyePosition(), pPlayer->EyePosition() + vecFwd * m_flReticleDist, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr); Vector vecAim = tr.endpos; if (mom_zone_grid.GetInt() > 0) VectorSnapToGrid(&vecAim, (float) mom_zone_grid.GetInt()); if (m_nBuildStage >= BUILDSTAGE_START) { Vector vecP2, vecP3, vecP4; if (m_nBuildStage >= BUILDSTAGE_END) { vecP3 = m_vecBuildEnd; } else { vecP3 = vecAim; } vecP3[2] = m_vecBuildStart[2]; // Bottom vecP2[0] = m_vecBuildStart[0]; vecP2[1] = vecP3[1]; vecP2[2] = m_vecBuildStart[2]; vecP4[0] = vecP3[0]; vecP4[1] = m_vecBuildStart[1]; vecP4[2] = m_vecBuildStart[2]; DebugDrawLine(m_vecBuildStart, vecP2, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP2, vecP3, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP3, vecP4, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP4, m_vecBuildStart, 255, 255, 255, true, -1.0f); if (m_nBuildStage >= BUILDSTAGE_END) { Vector vecP5, vecP6, vecP8; m_vecBuildEnd[2] = SnapToGrid(m_vecBuildStart[2] + GetZoneHeightToPlayer(pPlayer), (float) mom_zone_grid.GetInt()); // Top vecP5 = m_vecBuildStart; vecP5.z = m_vecBuildEnd[2]; vecP6 = vecP2; vecP6.z = m_vecBuildEnd[2]; vecP8 = vecP4; vecP8.z = m_vecBuildEnd[2]; DebugDrawLine(vecP5, vecP6, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP6, m_vecBuildEnd, 255, 255, 255, true, -1.0f); DebugDrawLine(m_vecBuildEnd, vecP8, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP8, vecP5, 255, 255, 255, true, -1.0f); // Bottom to top DebugDrawLine(m_vecBuildStart, vecP5, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP2, vecP6, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP3, m_vecBuildEnd, 255, 255, 255, true, -1.0f); DebugDrawLine(vecP4, vecP8, 255, 255, 255, true, -1.0f); } } // Draw surface normal. Makes it a bit easier to see where reticle is hitting. if (tr.DidHit()) { DebugDrawLine(vecAim, vecAim + tr.plane.normal * 24.0f, 0, 0, 255, true, -1.0f); } DrawReticle(&vecAim, (mom_zone_grid.GetInt() > 0) ? ((float) mom_zone_grid.GetInt() / 2.0f) : 8.0f); }
void CBulletManager::SimulateBullet(CBullet& oBullet, float dt) { Vector vecOriginal = oBullet.m_vecOrigin; Assert(oBullet.m_hShooter.Get()); if (!oBullet.m_hShooter) return; bool bHasTraveledBefore = false; if (oBullet.m_flDistanceTraveled > 0) bHasTraveledBefore = true; // initialize these before the penetration loop, we'll need them to make our tracer after Vector vecTracerSrc = oBullet.m_vecOrigin; trace_t tr; // main enter bullet trace float flRange = dt; if (flRange < 0) flRange = 8000; bool bFullPenetrationDistance = false; Vector vecEnd = oBullet.m_vecOrigin + oBullet.m_vecDirection * flRange; int i; for (i = oBullet.m_iPenetrations; i < da_bullet_penetrations.GetInt(); i++) { CTraceFilterSimpleList tf(COLLISION_GROUP_NONE); tf.AddEntityToIgnore(oBullet.m_hShooter); for (int j = 0; j < oBullet.m_ahObjectsHit.Count(); j++) tf.AddEntityToIgnore(oBullet.m_ahObjectsHit[j]); UTIL_TraceLine( oBullet.m_vecOrigin, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &tf, &tr ); if (da_bullet_debug.GetBool()) { #ifdef CLIENT_DLL DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 0, 255, 255, true, dt<0?10:0.1); #else DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 255, 255, 0, true, dt<0?10:0.1); #endif } Vector vecTraceEnd = tr.endpos; bool bBSPModel = tr.DidHitWorld(); if (tr.allsolid) { oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length(); oBullet.m_vecOrigin = vecEnd; break; // We're inside something. Do nothing. } if ( sv_showimpacts.GetBool() && tr.fraction < 1.0f ) { #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, sv_showimpacts.GetFloat() ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( sv_showimpacts.GetFloat(), true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, sv_showimpacts.GetFloat() ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( sv_showimpacts.GetFloat(), true ); } #endif } Assert(oBullet.m_iBulletType > 0); int iDamageType = DMG_BULLET | DMG_NEVERGIB | GetAmmoDef()->DamageType(oBullet.m_iBulletType); if (i == 0) iDamageType |= DMG_DIRECT; if (tr.startsolid) { trace_t tr2; UTIL_TraceLine( tr.endpos - oBullet.m_vecDirection, oBullet.m_vecOrigin, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr2 ); // let's have a bullet exit effect if we penetrated a solid surface if (oBullet.m_bDoEffects && tr2.m_pEnt && tr2.m_pEnt->IsBSPModel()) UTIL_ImpactTrace( &tr2, iDamageType ); // ignore the entity we just hit for the next trace to avoid weird impact behaviors oBullet.m_ahObjectsHit.AddToTail(tr2.m_pEnt); } if ( tr.fraction == 1.0f ) { oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length(); oBullet.m_vecOrigin = vecEnd; break; // we didn't hit anything, stop tracing shoot } weapontype_t eWeaponType = WT_NONE; CSDKWeaponInfo *pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(oBullet.m_eWeaponID); Assert(pWeaponInfo); if (pWeaponInfo) eWeaponType = pWeaponInfo->m_eWeaponType; float flDamageMultiplier = 1; float flMaxRange = 3000; // Power formula works like so: // pow( x, distance/y ) // The damage will be at 1 when the distance is 0 units, and at // x% when the distance is y units, with a gradual decay approaching zero switch (eWeaponType) { case WT_RIFLE: flDamageMultiplier = 0.75f; flMaxRange = 3000; break; case WT_SHOTGUN: flDamageMultiplier = 0.40f; flMaxRange = 500; break; case WT_SMG: flDamageMultiplier = 0.50f; flMaxRange = 1000; break; case WT_PISTOL: default: flDamageMultiplier = 0.55f; flMaxRange = 1500; break; } flMaxRange *= oBullet.m_hShooter->m_Shared.ModifySkillValue(1, 0.5f, SKILL_MARKSMAN); //calculate the damage based on the distance the bullet travelled. oBullet.m_flDistanceTraveled += tr.fraction * flRange; float flCurrentDistance = oBullet.m_flDistanceTraveled; // First 500 units, no decrease in damage. if (eWeaponType == WT_SHOTGUN) flCurrentDistance -= 350; else flCurrentDistance -= 500; if (flCurrentDistance < 0) flCurrentDistance = 0; if (flCurrentDistance > flMaxRange) flCurrentDistance = flMaxRange; float flDistanceMultiplier = pow(flDamageMultiplier, (flCurrentDistance / flMaxRange)); if( oBullet.m_bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { CBaseEntity* pIgnore; if (oBullet.m_ahObjectsHit.Count()) pIgnore = oBullet.m_ahObjectsHit.Tail(); else pIgnore = oBullet.m_hShooter; trace_t waterTrace; UTIL_TraceLine( oBullet.m_vecOrigin, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), pIgnore, 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; //Tony; only while using teams do we check for friendly fire. if ( DAGameRules()->IsTeamplay() && pEntity && pEntity->IsPlayer() && (pEntity->GetBaseAnimating() && !pEntity->GetBaseAnimating()->IsRagdoll()) ) { if ( pEntity->GetTeamNumber() != oBullet.m_hShooter->GetTeamNumber() ) UTIL_ImpactTrace( &tr, iDamageType ); } //Tony; non player, just go nuts, else UTIL_ImpactTrace( &tr, iDamageType ); } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL float flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i+1); // Each iteration the bullet drops in strength if (oBullet.m_hShooter->IsStyleSkillActive(SKILL_MARKSMAN)) flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i/2+1); // Each iteration the bullet drops in strength but not nearly as much. ClearMultiDamage(); CTakeDamageInfo info( oBullet.m_hShooter, oBullet.m_hShooter, oBullet.m_hWeapon, flBulletDamage, iDamageType ); CalculateBulletDamageForce( &info, oBullet.m_iBulletType, oBullet.m_vecDirection, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, oBullet.m_vecDirection, &tr ); oBullet.m_hShooter->TraceAttackToTriggers( info, tr.startpos, tr.endpos, oBullet.m_vecDirection ); ApplyMultiDamage(); #else flDistanceMultiplier = flDistanceMultiplier; // Silence warning. #endif if (tr.m_pEnt && !FStrEq(tr.m_pEnt->GetClassname(), "worldspawn")) oBullet.m_ahObjectsHit.AddToTail(tr.m_pEnt); float flPenetrationDistance; switch (eWeaponType) { case WT_RIFLE: flPenetrationDistance = 25; break; case WT_SHOTGUN: flPenetrationDistance = 5; break; case WT_SMG: flPenetrationDistance = 15; break; case WT_PISTOL: default: flPenetrationDistance = 15; break; } flPenetrationDistance = oBullet.m_hShooter->m_Shared.ModifySkillValue(flPenetrationDistance, 1, SKILL_MARKSMAN); Vector vecBackwards = tr.endpos + oBullet.m_vecDirection * flPenetrationDistance; if (tr.m_pEnt->IsBSPModel()) UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr ); else UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_HITBOX, NULL, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) { bFullPenetrationDistance = true; break; } // Set up the next trace. One unit in the direction of fire so that we firmly embed // ourselves in whatever solid was hit, to make sure we don't hit it again on next trace. if (dt < 0 && bBSPModel) { UTIL_TraceLine( vecTraceEnd + oBullet.m_vecDirection, vecTraceEnd + oBullet.m_vecDirection * flPenetrationDistance, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) oBullet.m_vecOrigin = tr.startpos + oBullet.m_vecDirection; else oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection; } else oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection; } oBullet.m_iPenetrations = i; // the bullet's done penetrating, let's spawn our particle system if (oBullet.m_bDoEffects && dt < 0) oBullet.m_hShooter->MakeTracer( oBullet.m_vecOrigin, tr, TRACER_TYPE_DEFAULT, !bHasTraveledBefore ); #ifdef CLIENT_DLL if (oBullet.m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE) ClientLeafSystem()->RenderableChanged( oBullet.m_hRenderHandle ); #endif if (bFullPenetrationDistance || oBullet.m_iPenetrations >= da_bullet_penetrations.GetInt()) oBullet.Deactivate(); if (dt < 0) oBullet.Deactivate(); if (!bHasTraveledBefore && oBullet.m_flCurrAlpha == 0 && oBullet.m_flGoalAlpha == 0) oBullet.m_bActive = false; if (da_bullet_debug.GetBool()) { #ifdef CLIENT_DLL DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 0, 0, 255, true, dt<0?10:0.1); #else DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 255, 0, 0, true, dt<0?10:0.1); #endif } }