Files
HL2Overcharged/game/client/C_entitydissolveegon.cpp
2025-05-21 21:09:22 +03:00

716 lines
20 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "iviewrender.h"
#include "view.h"
#include "studio.h"
#include "bone_setup.h"
#include "model_types.h"
#include "beamdraw.h"
#include "engine/ivdebugoverlay.h"
#include "iviewrender_beams.h"
#include "fx.h"
#include "iefx.h"
#include "dlight.h"
#include "IEffects.h"
#include "c_entitydissolveegon.h"
#include "movevars_shared.h"
#include "clienteffectprecachesystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CLIENTEFFECT_REGISTER_BEGIN(PrecacheEffectBuild2)
CLIENTEFFECT_MATERIAL("effects/tesla_glow_noz")
CLIENTEFFECT_MATERIAL("effects/spark")
CLIENTEFFECT_MATERIAL("effects/combinemuzzle2")
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT(C_EntityDissolveEgon, DT_EntityDissolveEgon, CEntityDissolveEgon)
RecvPropTime(RECVINFO(m_flStartTime)),
RecvPropFloat(RECVINFO(m_flFadeOutStart)),
RecvPropFloat(RECVINFO(m_flFadeOutLength)),
RecvPropFloat(RECVINFO(m_flFadeOutModelStart)),
RecvPropFloat(RECVINFO(m_flFadeOutModelLength)),
RecvPropFloat(RECVINFO(m_flFadeInStart)),
RecvPropFloat(RECVINFO(m_flFadeInLength)),
RecvPropInt(RECVINFO(m_nDissolveType)),
RecvPropVector(RECVINFO(m_vDissolverOrigin)),
RecvPropInt(RECVINFO(m_nMagnitude)),
END_RECV_TABLE()
extern PMaterialHandle g_Material_Spark;
PMaterialHandle g_Material_AR2Glow = NULL;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityDissolveEgon::C_EntityDissolveEgon(void)
{
m_bLinkedToServerEnt = true;
m_pController = NULL;
m_bCoreExplode = false;
m_vEffectColor = Vector(255, 255, 255);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::GetRenderBounds(Vector& theMins, Vector& theMaxs)
{
if (GetMoveParent())
{
GetMoveParent()->GetRenderBounds(theMins, theMaxs);
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged(updateType);
if (updateType == DATA_UPDATE_CREATED)
{
m_flNextSparkTime = m_flStartTime;
SetNextClientThink(CLIENT_THINK_ALWAYS);
}
}
//-----------------------------------------------------------------------------
// Cleanup
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::UpdateOnRemove(void)
{
if (m_pController)
{
physenv->DestroyMotionController(m_pController);
m_pController = NULL;
}
BaseClass::UpdateOnRemove();
}
//------------------------------------------------------------------------------
// Apply the forces to the entity
//------------------------------------------------------------------------------
IMotionEvent::simresult_e C_EntityDissolveEgon::Simulate(IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular)
{
linear.Init();
angular.Init();
// Make it zero g
linear.z -= -1.02 * GetCurrentGravity();
Vector vel;
AngularImpulse angVel;
pObject->GetVelocity(&vel, &angVel);
vel += linear * deltaTime; // account for gravity scale
Vector unitVel = vel;
Vector unitAngVel = angVel;
float speed = VectorNormalize(unitVel);
// float angSpeed = VectorNormalize( unitAngVel );
// float speedScale = 0.0;
// float angSpeedScale = 0.0;
float flLinearLimit = 50;
float flLinearLimitDelta = 40;
if (speed > flLinearLimit)
{
float flDeltaVel = (flLinearLimit - speed) / deltaTime;
if (flLinearLimitDelta != 0.0f)
{
float flMaxDeltaVel = -flLinearLimitDelta / deltaTime;
if (flDeltaVel < flMaxDeltaVel)
{
flDeltaVel = flMaxDeltaVel;
}
}
VectorMA(linear, flDeltaVel, unitVel, linear);
}
return SIM_GLOBAL_ACCELERATION;
}
//-----------------------------------------------------------------------------
// Tesla effect
//-----------------------------------------------------------------------------
static void FX_BuildTesla(C_BaseEntity *pEntity, Vector &vecOrigin, Vector &vecEnd)
{
BeamInfo_t beamInfo;
beamInfo.m_pStartEnt = pEntity;
beamInfo.m_nStartAttachment = 0;
beamInfo.m_pEndEnt = NULL;
beamInfo.m_nEndAttachment = 0;
beamInfo.m_nType = TE_BEAMTESLA;
beamInfo.m_vecStart = vecOrigin;
beamInfo.m_vecEnd = vecEnd;
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
beamInfo.m_flHaloScale = 0.0;
beamInfo.m_flLife = random->RandomFloat(0.25f, 1.0f);
beamInfo.m_flWidth = random->RandomFloat(8.0f, 14.0f);
beamInfo.m_flEndWidth = 1.0f;
beamInfo.m_flFadeLength = 0.5f;
beamInfo.m_flAmplitude = 24;
beamInfo.m_flBrightness = 255.0;
beamInfo.m_flSpeed = 150.0f;
beamInfo.m_nStartFrame = 0.0;
beamInfo.m_flFrameRate = 30.0;
beamInfo.m_flRed = 138.0;
beamInfo.m_flGreen = 112.0;
beamInfo.m_flBlue = 234.0;
beamInfo.m_nSegments = 18;
beamInfo.m_bRenderable = true;
beamInfo.m_nFlags = 0; //FBEAM_ONLYNOISEONCE;
beams->CreateBeamEntPoint(beamInfo);
}
//-----------------------------------------------------------------------------
// Purpose: Tesla effect
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::BuildTeslaEffect(mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset)
{
Vector vecOrigin;
QAngle vecAngles;
MatrixGetColumn(hitboxToWorld, 3, vecOrigin);
MatrixAngles(hitboxToWorld, vecAngles.Base());
C_BaseEntity *pEntity = GetMoveParent();
// Make a couple of tries at it
int iTries = -1;
Vector vecForward;
trace_t tr;
do
{
iTries++;
// Some beams are deliberatly aimed around the point, the rest are random.
if (!bRandom)
{
QAngle vecTemp = vecAngles;
vecTemp[YAW] += flYawOffset;
AngleVectors(vecTemp, &vecForward);
// Randomly angle it up or down
vecForward.z = RandomFloat(-1, 1);
}
else
{
vecForward = RandomVector(-1, 1);
}
UTIL_TraceLine(vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr);
} while (tr.fraction >= 1.0 && iTries < 3);
Vector vecEnd = tr.endpos - (vecForward * 8);
// Only spark & glow if we hit something
if (tr.fraction < 1.0)
{
if (!EffectOccluded(tr.endpos))
{
// Move it towards the camera
Vector vecFlash = tr.endpos;
Vector vecForward;
AngleVectors(MainViewAngles(), &vecForward);
vecFlash -= (vecForward * 8);
g_pEffects->EnergySplash(vecFlash, -vecForward, false);
// End glow
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create("dust");
pSimple->SetSortOrigin(vecFlash);
SimpleParticle *pParticle;
pParticle = (SimpleParticle *)pSimple->AddParticle(sizeof(SimpleParticle), pSimple->GetPMaterial("effects/tesla_glow_noz"), vecFlash);
if (pParticle != NULL)
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = RandomFloat(0.5, 1);
pParticle->m_vecVelocity = vec3_origin;
Vector color(1, 1, 1);
float colorRamp = RandomFloat(0.75f, 1.25f);
pParticle->m_uchColor[0] = MIN(1.0f, color[0] * colorRamp) * 255.0f;
pParticle->m_uchColor[1] = MIN(1.0f, color[1] * colorRamp) * 255.0f;
pParticle->m_uchColor[2] = MIN(1.0f, color[2] * colorRamp) * 255.0f;
pParticle->m_uchStartSize = RandomFloat(6, 13);
pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 10;
pParticle->m_flRoll = RandomFloat(0, 360);
pParticle->m_flRollDelta = 0;
}
}
}
// Build the tesla
FX_BuildTesla(pEntity, vecOrigin, tr.endpos);
}
//-----------------------------------------------------------------------------
// Sorts the components of a vector
//-----------------------------------------------------------------------------
static inline void SortAbsVectorComponents(const Vector& src, int* pVecIdx)
{
Vector absVec(fabs(src[0]), fabs(src[1]), fabs(src[2]));
int maxIdx = (absVec[0] > absVec[1]) ? 0 : 1;
if (absVec[2] > absVec[maxIdx])
{
maxIdx = 2;
}
// always choose something right-handed....
switch (maxIdx)
{
case 0:
pVecIdx[0] = 1;
pVecIdx[1] = 2;
pVecIdx[2] = 0;
break;
case 1:
pVecIdx[0] = 2;
pVecIdx[1] = 0;
pVecIdx[2] = 1;
break;
case 2:
pVecIdx[0] = 0;
pVecIdx[1] = 1;
pVecIdx[2] = 2;
break;
}
}
//-----------------------------------------------------------------------------
// Compute the bounding box's center, size, and basis
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::ComputeRenderInfo(mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec)
{
// Compute the center of the hitbox in worldspace
Vector vecHitboxCenter;
VectorAdd(pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter);
vecHitboxCenter *= 0.5f;
VectorTransform(vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin);
// Get the object's basis
Vector vec[3];
MatrixGetColumn(hitboxToWorld, 0, vec[0]);
MatrixGetColumn(hitboxToWorld, 1, vec[1]);
MatrixGetColumn(hitboxToWorld, 2, vec[2]);
// vec[1] *= -1.0f;
Vector vecViewDir;
VectorSubtract(CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir);
VectorNormalize(vecViewDir);
// Project the shadow casting direction into the space of the hitbox
Vector localViewDir;
localViewDir[0] = DotProduct(vec[0], vecViewDir);
localViewDir[1] = DotProduct(vec[1], vecViewDir);
localViewDir[2] = DotProduct(vec[2], vecViewDir);
// Figure out which vector has the largest component perpendicular
// to the view direction...
// Sort by how perpendicular it is
int vecIdx[3];
SortAbsVectorComponents(localViewDir, vecIdx);
// Here's our hitbox basis vectors; namely the ones that are
// most perpendicular to the view direction
*pXVec = vec[vecIdx[0]];
*pYVec = vec[vecIdx[1]];
// Project them into a plane perpendicular to the view direction
*pXVec -= vecViewDir * DotProduct(vecViewDir, *pXVec);
*pYVec -= vecViewDir * DotProduct(vecViewDir, *pYVec);
VectorNormalize(*pXVec);
VectorNormalize(*pYVec);
// Compute the hitbox size
Vector boxSize;
VectorSubtract(pHitBox->bbmax, pHitBox->bbmin, boxSize);
// We project the two longest sides into the vectors perpendicular
// to the projection direction, then add in the projection of the perp direction
Vector2D size(boxSize[vecIdx[0]], boxSize[vecIdx[1]]);
size.x *= fabs(DotProduct(vec[vecIdx[0]], *pXVec));
size.y *= fabs(DotProduct(vec[vecIdx[1]], *pYVec));
// Add the third component into x and y
size.x += boxSize[vecIdx[2]] * fabs(DotProduct(vec[vecIdx[2]], *pXVec));
size.y += boxSize[vecIdx[2]] * fabs(DotProduct(vec[vecIdx[2]], *pYVec));
// Bloat a bit, since the shadow wants to extend outside the model a bit
size *= 2.0f;
// Clamp the minimum size
Vector2DMax(size, Vector2D(10.0f, 10.0f), size);
// Factor the size into the xvec + yvec
(*pXVec) *= size.x * 0.5f;
(*pYVec) *= size.y * 0.5f;
}
//-----------------------------------------------------------------------------
// Sparks!
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::DoSparks(mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES])
{
if (m_flNextSparkTime > gpGlobals->curtime)
return;
float dt = m_flStartTime + m_flFadeOutStart - gpGlobals->curtime;
dt = clamp(dt, 0.0f, m_flFadeOutStart);
float flNextTime;
if (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL)
{
flNextTime = SimpleSplineRemapVal(dt, 0.0f, m_flFadeOutStart, 2.0f * TICK_INTERVAL, 0.4f);
}
else
{
// m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT);
flNextTime = SimpleSplineRemapVal(dt, 0.0f, m_flFadeOutStart, 0.3f, 1.0f);
}
m_flNextSparkTime = gpGlobals->curtime + flNextTime;
// Send out beams around us
int iNumBeamsAround = 2;
int iNumRandomBeams = 1;
int iTotalBeams = iNumBeamsAround + iNumRandomBeams;
float flYawOffset = RandomFloat(0, 360);
for (int i = 0; i < iTotalBeams; i++)
{
int nHitbox = random->RandomInt(0, set->numhitboxes - 1);
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
float flActualYawOffset = 0;
bool bRandom = (i >= iNumBeamsAround);
if (!bRandom)
{
flActualYawOffset = anglemod(flYawOffset + ((360 / iTotalBeams) * i));
}
BuildTeslaEffect(pBox, *hitboxbones[pBox->bone], bRandom, flActualYawOffset);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::SetupEmitter(void)
{
if (!m_pEmitter)
{
m_pEmitter = CSimpleEmitter::Create("C_EntityDissolveEgon");
m_pEmitter->SetSortOrigin(GetAbsOrigin());
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolveEgon::GetFadeInPercentage(void)
{
float dt = gpGlobals->curtime - m_flStartTime;
if (dt > m_flFadeOutStart)
return 1.0f;
if (dt < m_flFadeInStart)
return 0.0f;
if ((dt > m_flFadeInStart) && (dt < m_flFadeInStart + m_flFadeInLength))
{
dt -= m_flFadeInStart;
return (dt / m_flFadeInLength);
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolveEgon::GetFadeOutPercentage(void)
{
float dt = gpGlobals->curtime - m_flStartTime;
if (dt < m_flFadeInStart)
return 1.0f;
if (dt > m_flFadeOutStart)
{
dt -= m_flFadeOutStart;
if (dt > m_flFadeOutLength)
return 0.0f;
return 1.0f - (dt / m_flFadeOutLength);
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolveEgon::GetModelFadeOutPercentage(void)
{
float dt = gpGlobals->curtime - m_flStartTime;
if (dt < m_flFadeOutModelStart)
return 1.0f;
if (dt > m_flFadeOutModelStart)
{
dt -= m_flFadeOutModelStart;
if (dt > m_flFadeOutModelLength)
return 0.0f;
return 1.0f - (dt / m_flFadeOutModelLength);
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolveEgon::ClientThink(void)
{
C_BaseEntity *pEnt = GetMoveParent();
if (!pEnt)
return;
bool bIsRagdoll;
#ifdef TF_CLIENT_DLL
bIsRagdoll = true;
#else
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if (!pAnimating)
return;
bIsRagdoll = pAnimating->IsRagdoll();
#endif
// NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight
// the server ragdoll (or any server physics) on the client
if ((!m_pController) && (m_nDissolveType == ENTITY_DISSOLVE_NORMAL) && bIsRagdoll)
{
IPhysicsObject *ppList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
int nCount = pEnt->VPhysicsGetObjectList(ppList, ARRAYSIZE(ppList));
if (nCount > 0)
{
m_pController = physenv->CreateMotionController(this);
for (int i = 0; i < nCount; ++i)
{
m_pController->AttachObject(ppList[i], true);
}
}
}
color32 color;
color.r = (1.0f - GetFadeInPercentage()) * m_vEffectColor.x;
color.g = (1.0f - GetFadeInPercentage()) * m_vEffectColor.y;
color.b = (1.0f - GetFadeInPercentage()) * m_vEffectColor.z;
color.a = GetModelFadeOutPercentage() * 255.0f;
// Setup the entity fade
pEnt->SetRenderMode(kRenderTransColor);
pEnt->SetRenderColor(color.r, color.g, color.b, color.a);
if (GetModelFadeOutPercentage() <= 0.2f)
{
m_bCoreExplode = true;
}
// If we're dead, fade out
/*if (GetFadeOutPercentage() <= 0.0f)
{
// Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed
// because when the server says to destroy it, the client won't be able to find it.
// ClientEntityList().RemoveEntity( GetClientHandle() );
partition->Remove(PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle());
RemoveFromLeafSystem();
//FIXME: Ick!
//Adrian: I'll assume we don't need the ragdoll either so I'll remove that too.
if (m_bLinkedToServerEnt == false)
{
Release();
C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> (pEnt);
if (pRagdoll)
{
pRagdoll->ReleaseRagdoll();
}
#ifdef TF_CLIENT_DLL
else
{
pEnt->Release();
}
#endif
}
}*/
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityDissolveEgon::DrawModel(int flags)
{
// See if we should draw
if (gpGlobals->frametime == 0 || m_bReadyToDraw == false)
return 0;
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if (pAnimating == NULL)
return 0;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
if (pAnimating->HitboxToWorldTransforms(hitboxbones) == false)
return 0;
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel(pAnimating->GetModel());
if (pStudioHdr == NULL)
return false;
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet(pAnimating->GetHitboxSet());
if (set == NULL)
return false;
QAngle Ang;
// Make sure the emitter is setup properly
SetupEmitter();
// Get fade percentages for the effect
float fadeInPerc = GetFadeInPercentage();
float fadeOutPerc = GetFadeOutPercentage();
float fadePerc = (fadeInPerc >= 1.0f) ? fadeOutPerc : fadeInPerc;
Vector vecSkew = vec3_origin;
// Do extra effects under certain circumstances
if ((fadePerc < 0.99f) && ((m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT)))
{
DoSparks(set, hitboxbones);
}
// Skew the particles in front or in back of their targets
vecSkew = CurrentViewForward() * (8.0f - ((1.0f - fadePerc) * 32.0f));
float spriteScale = ((gpGlobals->curtime - m_flStartTime) / m_flFadeOutLength);
spriteScale = clamp(spriteScale, 0.75f, 1.0f);
// Cache off this material reference
/*if (g_Material_Spark == NULL)
{
g_Material_Spark = ParticleMgr()->GetPMaterial("effects/spark");
}
if (g_Material_AR2Glow == NULL)
{
g_Material_AR2Glow = ParticleMgr()->GetPMaterial("effects/combinemuzzle2");
}
SimpleParticle *sParticle;*/
for (int i = 0; i < set->numhitboxes; ++i)
{
Vector vecAbsOrigin, xvec, yvec;
mstudiobbox_t *pBox = set->pHitbox(i);
ComputeRenderInfo(pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec);
Vector offset;
Vector xDir, yDir;
xDir = xvec;
//float xScale = VectorNormalize(xDir) * 0.75f;
yDir = yvec;
//float yScale = VectorNormalize(yDir) * 0.75f;
int numParticles = clamp(3.0f * fadePerc, 0.f, 3.f);
int iTempParts = 2;
if (m_nDissolveType == ENTITY_DISSOLVE_CORE)
{
if (m_bCoreExplode == true)
{
numParticles = 15;
iTempParts = 20;
}
}
/*for (int j = 0; j < iTempParts; j++)
{
// Skew the origin
offset = xDir * Helper_RandomFloat(-xScale*0.5f, xScale*0.5f) + yDir * Helper_RandomFloat(-yScale*0.5f, yScale*0.5f);
offset += vecSkew;
VectorAngles(vecAbsOrigin + offset, Ang);
AddEffects(EF_EGONDISSOLVELIGHT);
DispatchParticleEffect("dissolve_egon_warp", vecAbsOrigin + offset, Ang, NULL);
}
for (int j = 0; j < numParticles; j++)
{
offset = xDir * Helper_RandomFloat(-xScale*0.5f, xScale*0.5f) + yDir * Helper_RandomFloat(-yScale*0.5f, yScale*0.5f);
offset += vecSkew;
AddEffects(EF_EGONDISSOLVELIGHT);
VectorAngles(vecAbsOrigin + offset, Ang);
DispatchParticleEffect("dissolve_egon", vecAbsOrigin + offset, Ang, NULL);
}
dlight_t *el = effects->CL_AllocDlight(index);//( index );
el->origin = offset;
el->color.r = 64;
el->color.g = 128;
el->color.b = 255;
el->color.exponent = 5;
el->radius = random->RandomInt(32, 128);
el->decay = el->radius / 0.05f;
el->die = gpGlobals->curtime + 0.05f;*/
}
return 1;
}