Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

875 lines
21 KiB

/****************************************************************
* *
* particules.cpp *
* *
* par Julien *
* *
****************************************************************/
// code du syst
// et des decals
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "triangleapi.h"
#include <string.h>
#include "cdll_int.h"
#include "pmtrace.h"
#include "event_api.h"
#include "pm_defs.h"
#include "parsemsg.h"
#include "eventscripts.h"
#include "r_efx.h"
extern void EV_HLDM_EjectParticules ( Vector vecOrigin, Vector vecNormal, char chTextureType, int decal, int iParticules );
void VectorAngles( const float *forward, float *angles );
extern vec3_t v_angles;
#define PARTICULES_LARGEUR 2
#define DECALS_LARGEUR 4
//========================
// ajout de particule
//
void CHudParticules :: AddParticule ( vec3_t origin, vec3_t angles, vec3_t velocity, vec3_t avelocity, char model [64], int deathtime, int flags )
{
int iIndex;
for ( iIndex = 0 ; iIndex < MAX_PARTICULES ; iIndex ++ )
{
if ( m_pParticules [ iIndex ].libre == 1 )
break;
}
// array rempli
if ( m_pParticules [ iIndex ].libre != 1 )
{
// gEngfuncs.Con_Printf ( "client.dll : Particule overflow : > %i\n", MAX_PARTICULES ); //alertatconsole
return;
}
//remplissage du nouveau tableau de donnees
m_pParticules [ iIndex ].origin = origin;
m_pParticules [ iIndex ].angles = angles;
m_pParticules [ iIndex ].velocity = velocity;
m_pParticules [ iIndex ].avelocity = avelocity;
m_pParticules [ iIndex ].deathtime = deathtime;
m_pParticules [ iIndex ].flags = flags;
m_pParticules [ iIndex ].libre = 0;
strcpy ( m_pParticules [ iIndex ].model, model );
}
//=========================
// ajout de decal
//
void CHudParticules :: AddDecal ( vec3_t origin, vec3_t angles, char model [64], float deathtime, int flags )
{
// recherche de place libre
int iIndex;
int iIndexNew = 0;
for ( iIndex = 0 ; iIndex < MAX_DECALS ; iIndex ++ )
{
if ( m_pDecals [ iIndex ].libre == 1 )
break;
}
// place libre
if ( m_pDecals [ iIndex ].libre == 1 )
{
// demande acceptee
iIndexNew = iIndex;
}
// tableau rempli
else
{
float age = m_pDecals[0].deathtime;
int oldindex = 0;
// cherche le plus ancien
for ( iIndex = 0; iIndex < MAX_DECALS ; iIndex ++ )
{
if ( m_pDecals[iIndex].deathtime < age )
{
age = m_pDecals[iIndex].deathtime;
oldindex = iIndex;
}
}
// detruit le plus ancient
RemoveDecal ( oldindex );
// prend la place nouvellement libre
// demande acceptee
iIndexNew = oldindex;
// actualise l age minimum
age = m_pDecals[0].deathtime;
for ( iIndex = 0; iIndex < MAX_DECALS ; iIndex ++ )
{
if ( m_pDecals[iIndex].deathtime < age )
age = m_pDecals[iIndex].deathtime;
}
}
// enregistre
m_pDecals[iIndexNew].angles = angles;
m_pDecals[iIndexNew].deathtime = deathtime;
m_pDecals[iIndexNew].flags = flags;
m_pDecals[iIndexNew].libre = 0;
m_pDecals[iIndexNew].origin = origin;
strcpy ( m_pDecals [ iIndex ].model, model );
// electro-rocket
if ( flags & ( FLAG_DECAL_DISK | flags & FLAG_DECAL_SG | FLAG_DECAL_XENO ) )
{
m_pDecals[iIndexNew].iRndSensX = m_pDecals[iIndexNew].iRndSensY = 1;
return;
}
// fixe
Vector forward, right, up;
AngleVectors ( m_pDecals[iIndexNew].angles, forward, right, up );
pmtrace_t pmtrace;
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( m_pDecals[iIndexNew].origin - forward.Normalize()*0.2, m_pDecals[iIndexNew].origin, PM_STUDIO_BOX | PM_STUDIO_IGNORE, -1, &pmtrace );
physent_s *pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
int entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( &pmtrace );
if ( pmtrace.fraction == 0.0 && pe && pe->solid == SOLID_BSP && entity != 0 )
{
// contre un mur et contre une entit
m_pDecals[iIndexNew].entity = entity;
m_pDecals[iIndexNew].offset = m_pDecals[iIndexNew].origin - pe->origin;
m_pDecals[iIndexNew].angoffset = pe->angles;
m_pDecals[iIndexNew].oldangles = m_pDecals[iIndexNew].angles;
cl_entity_s *pClEnt = GetEntity( entity );
// pas de d
if ( pe->rendermode != kRenderNormal && pClEnt->curstate.renderamt == 0 )
{
RemoveDecal ( iIndexNew );
return;
}
if ( pe->rendermode == kRenderTransTexture )
{
//entit
if ( pClEnt->curstate.renderamt == 0 && m_pDecals[iIndexNew].flags & FLAG_DECAL_GLASS )
{
RemoveDecal ( iIndexNew );
return;
}
// entit
else if ( m_pDecals[iIndexNew].flags & FLAG_DECAL_GLASS && gEngfuncs.pfnRandomLong (0,3) != 0 )
{
m_pDecals[iIndexNew].flags |= FLAG_DECAL_WIDEGLASS;
}
}
// grille
else if ( pe->rendermode == kRenderTransAlpha )
{
RemoveDecal ( iIndexNew );
return;
}
}
else
{
m_pDecals[iIndexNew].entity = 0;
m_pDecals[iIndexNew].offset = m_pDecals[iIndexNew].angoffset = Vector(0,0,0);
}
// taille al
float iRnd = gEngfuncs.pfnRandomFloat( 0.75, 1 );
if ( m_pDecals[iIndexNew].flags & FLAG_DECAL_WIDEGLASS )
iRnd *= 6;
else if ( m_pDecals[iIndexNew].flags & FLAG_DECAL_GLASS )
iRnd *= 4;
m_pDecals[iIndexNew].iRndSensX = m_pDecals[iIndexNew].iRndSensY = iRnd;
iRnd = gEngfuncs.pfnRandomLong( 0, 1 );
m_pDecals[iIndexNew].iRndSensX = iRnd == 1 ? - m_pDecals[iIndexNew].iRndSensX : m_pDecals[iIndexNew].iRndSensX;
m_pDecals[iIndexNew].iRndSensY = iRnd == 1 ? - m_pDecals[iIndexNew].iRndSensY : m_pDecals[iIndexNew].iRndSensY;
// sens du crowbar
if ( m_pDecals[iIndexNew].flags & FLAG_DECAL_CROWBAR_INVERT )
m_pDecals[iIndexNew].iRndSensX = - m_pDecals[iIndexNew].iRndSensX;
// A FAIRE : enlever les d
// demande acceptee
return;
}
//===========================================
// application des lois physiques
int CHudParticules :: Draw ( float flTime )
{
static const Vector gravity (0,0,-400);
float delta = flTime - m_flLastTime;
m_flLastTime = flTime;
if ( delta == 0 )
return 1;
for ( int iIndex = 0; iIndex < MAX_PARTICULES ; iIndex ++ )
{
// fin de la liste
if ( m_pParticules [ iIndex ].libre == 1 )
continue;
vec3_t lastpos = m_pParticules [ iIndex ].origin;
if ( m_pParticules [ iIndex ].deathtime < flTime )
{
RemoveParticule ( iIndex );
continue;
}
m_pParticules[iIndex].angles = m_pParticules[iIndex].angles + m_pParticules[iIndex].avelocity * delta;
m_pParticules[iIndex].origin = m_pParticules[iIndex].origin + m_pParticules[iIndex].velocity * delta;
if ( !(m_pParticules[iIndex].flags & ( FLAG_PARTICULE_OUTRO1 | FLAG_PARTICULE_OUTRO2 | FLAG_PARTICULE_OUTRO3 | FLAG_PARTICULE_SMOKE )) )
{
m_pParticules[iIndex].velocity = m_pParticules[iIndex].velocity + gravity * delta;
}
if ( m_pParticules[iIndex].flags & FLAG_PARTICULE_OUTRO2 )
{
if ( m_pParticules [ iIndex ].deathtime - flTime < 4.5 )
{
m_pParticules[iIndex].velocity = m_pParticules[iIndex].velocity.Normalize() * Q_max( 0, m_pParticules[iIndex].velocity.Length() - 10 * delta );
}
else if ( m_pParticules [ iIndex ].deathtime - flTime < 6)
{
int i = ( m_pParticules[iIndex].angles.x - 1.2 ) / 0.3;
m_pParticules[iIndex].velocity = m_pParticules[iIndex].velocity.Normalize() * 14 * ( 0.3 - i*0.03 ) * 2.5;
}
}
if ( m_pParticules[iIndex].flags & ( FLAG_PARTICULE_OUTRO1 | FLAG_PARTICULE_OUTRO2 | FLAG_PARTICULE_OUTRO3 ) )
{
if ( m_pParticules [ iIndex ].deathtime - flTime < 2.5 )
{
m_pParticules [ iIndex ].angles.y -= delta * 0.3 / 2.5;
m_pParticules [ iIndex ].angles.y = Q_max ( 0, m_pParticules [ iIndex ].angles.y );
}
}
pmtrace_t pmtrace;
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( lastpos, m_pParticules [ iIndex ].origin, PM_STUDIO_BOX | PM_WORLD_ONLY, -1, &pmtrace );
if ( pmtrace.fraction != 1 )
m_pParticules [ iIndex ].deathtime = gEngfuncs.GetClientTime();
}
for ( int iDecal = 0; iDecal < MAX_DECALS ; iDecal ++ )
{
// innocupp
if ( m_pDecals[iDecal].libre == 1 )
continue;
if ( m_pDecals[iDecal].deathtime < flTime )
{
RemoveDecal ( iDecal );
return 1;
}
if ( m_pDecals[iDecal].flags & FLAG_DECAL_DISK )
{
if ( m_pDecals[iDecal].iRndSensX < ELECTRO_DISK_MAX )
{
m_pDecals[iDecal].iRndSensX += ELECTRO_DISK_SPEED * delta;
m_pDecals[iDecal].iRndSensY = m_pDecals[iDecal].iRndSensX;
}
continue;
}
if ( m_pDecals[iDecal].flags & FLAG_DECAL_SG )
{
if ( m_pDecals[iDecal].iRndSensX < 8 )
{
m_pDecals[iDecal].iRndSensX += 16 * delta;
m_pDecals[iDecal].iRndSensY = m_pDecals[iDecal].iRndSensX = Q_min ( 8, m_pDecals[iDecal].iRndSensX );
}
continue;
}
if ( m_pDecals[iDecal].flags & FLAG_DECAL_XENO )
{
if ( m_pDecals[iDecal].iRndSensX < 3 )
{
m_pDecals[iDecal].iRndSensX += 3 * delta;
m_pDecals[iDecal].iRndSensY = m_pDecals[iDecal].iRndSensX = Q_min ( 3, m_pDecals[iDecal].iRndSensX );
}
continue;
}
Vector forward, right, up;
AngleVectors ( m_pDecals[iDecal].angles, forward, right, up );
pmtrace_t pmtrace;
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( m_pDecals[iDecal].origin - forward.Normalize()*0.35, m_pDecals[iDecal].origin, PM_STUDIO_BOX | PM_STUDIO_IGNORE, -1, &pmtrace );
physent_s *pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
int entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( &pmtrace );
// sprite anim
if ( m_pDecals[iDecal].flags & FLAG_DECAL_WIDEGLASS )
{
// 9.0 fps - - 5 frames max
m_pDecals[iDecal].flFrame += delta * 9;
m_pDecals[iDecal].flFrame = m_pDecals[iDecal].flFrame > 4 ? 4 : m_pDecals[iDecal].flFrame;
}
if ( m_pDecals[iDecal].entity != 0 )
{
//suit le d
cl_entity_t *pClEnt = GetEntity( m_pDecals[iDecal].entity );
if ( pClEnt == 0 )
{
m_pDecals[iDecal].entity = 0;
}
else if ( m_pDecals[iDecal].angoffset != pClEnt->angles )
{
// entit
float flLength = m_pDecals[iDecal].offset.Length();
vec3_t angDiff, angNewAngles;
VectorAngles( m_pDecals[iDecal].offset.Normalize(), angDiff );
angNewAngles = pClEnt->angles + ( angDiff - m_pDecals[iDecal].angoffset );
vec3_t forward, right, up;
angNewAngles.x += 180;
angNewAngles.y += 180;
AngleVectors ( angNewAngles, forward, right, up );
m_pDecals[iDecal].origin = pClEnt->origin + forward.Normalize() * flLength;
m_pDecals[iDecal].angles = pClEnt->angles + ( m_pDecals[iDecal].oldangles - m_pDecals[iDecal].angoffset );
}
else if ( ( ( pmtrace.startsolid == 1 && m_pDecals[iDecal].entity != 0 ) ||
( pmtrace.fraction == 0.0 && m_pDecals[iDecal].entity != 0 ) )
&& ( m_pDecals[iDecal].origin - pClEnt->origin != m_pDecals[iDecal].offset ) )
{
// porte coulissante
m_pDecals[iDecal].origin = pClEnt->origin + m_pDecals[iDecal].offset;
}
else if ( pmtrace.fraction != 0.0 )
{
// d
RemoveDecal ( iDecal );
}
}
else if ( pmtrace.fraction != 0.0 )
{
// d
RemoveDecal ( iDecal );
}
}
return 1;
}
//=================================
// suppression d une particule
void CHudParticules :: RemoveParticule ( int iIndex )
{
m_pParticules[iIndex].libre = 1;
m_pParticules[iIndex].angles = m_pParticules[iIndex].origin = m_pParticules[iIndex].avelocity = m_pParticules[iIndex].velocity = Vector ( 0,0,0 );
m_pParticules[iIndex].deathtime = m_pParticules[iIndex].flags = 0;
strcpy ( m_pParticules[iIndex].model, "" );
}
// suppression d'un d
void CHudParticules :: RemoveDecal ( int iIndex )
{
m_pDecals[iIndex].libre = 1;
m_pDecals[iIndex].angles = m_pDecals[iIndex].origin = m_pDecals[iIndex].offset = Vector ( 0,0,0 );
m_pDecals[iIndex].deathtime = 0;
m_pDecals[iIndex].flags = 0;
m_pDecals[iIndex].entity = 0;
// strcpy ( m_pDecals[iIndex].model, " " );
}
//=====================================
//
// trac
void CHudParticules :: DrawAll ( void )
{
//particules
int iIndex, iresult = 0;
for ( iIndex = 0; iIndex < MAX_PARTICULES ; iIndex ++ )
{
// fin de la liste
if ( m_pParticules [ iIndex ].libre == 1 )
continue;
iresult ++;
// vecteurs de base
vec3_t forward, right, up, vertex, ang;
if ( m_pParticules[iIndex].flags & ( FLAG_PARTICULE_OUTRO1 | FLAG_PARTICULE_OUTRO2 | FLAG_PARTICULE_OUTRO3 ) )
{
ang = v_angles + Vector(0.0f, 0.0f, m_pParticules[iIndex].angles.z );
}
else if ( m_pParticules[iIndex].flags & FLAG_PARTICULE_SMOKE )
{
ang = v_angles;
}
else
{
ang = m_pParticules[iIndex].angles;
}
AngleVectors ( ang, forward, right, up );
float largeurX = PARTICULES_LARGEUR / 2;
float largeurY = PARTICULES_LARGEUR / 2;
if ( m_pParticules[iIndex].flags & FLAG_PARTICULE_WOOD )
{
largeurY *= 0.5;
largeurX *= 2;
}
if ( m_pParticules[iIndex].flags & ( FLAG_PARTICULE_OUTRO1 | FLAG_PARTICULE_OUTRO2 | FLAG_PARTICULE_OUTRO3 ) )
{
largeurX = largeurY = m_pParticules[iIndex].angles.x;
}
if ( m_pParticules[iIndex].flags & FLAG_PARTICULE_SMOKE )
{
largeurX = largeurY = 0.75 * 32 * 0.5;
}
int modelindex;
struct model_s *mod = gEngfuncs.CL_LoadModel( m_pParticules[iIndex].model, &modelindex );
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)mod, 0 ); //chargement du sprite
// mode de transparence
if ( m_pParticules[iIndex].flags & ( FLAG_PARTICULE_OUTRO1 | FLAG_PARTICULE_OUTRO2 | FLAG_PARTICULE_OUTRO3 ) )
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
gEngfuncs.pTriAPI->Brightness( m_pParticules[iIndex].angles.y );
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, m_pParticules[iIndex].angles.y );
}
else if ( m_pParticules[iIndex].flags & FLAG_PARTICULE_SMOKE )
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
gEngfuncs.pTriAPI->Brightness( 240/255 );
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 240/255 );
}
else
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransAlpha );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
}
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //(des)activer le face culling
gEngfuncs.pTriAPI->Begin( TRI_QUADS ); //d
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); //premier vertex
vertex = m_pParticules[iIndex].origin - up*largeurY - right * largeurX;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); //deuxieme vertex
vertex = m_pParticules[iIndex].origin + right* largeurX - up*largeurY;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); //troisieme vertex
vertex = m_pParticules[iIndex].origin + right* largeurX + up* largeurY;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); //quatrieme vertex
vertex = m_pParticules[iIndex].origin + up* largeurX - right* largeurY;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->End(); //fin du trac
gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
}
int iDecalIndex, idecalresult = 0;
for ( iDecalIndex = 0; iDecalIndex < MAX_DECALS ; iDecalIndex ++ )
{
// emplacement vide
if ( m_pDecals [ iDecalIndex ].libre == 1 )
continue;
idecalresult ++;
// frame
int frame;
if ( m_pDecals[iDecalIndex].flags & FLAG_DECAL_WIDEGLASS )
frame = ( int ) m_pDecals[iDecalIndex].flFrame;
else
frame = 0;
//trac
vec3_t forward, right, up, vertex;
AngleVectors ( m_pDecals[iDecalIndex].angles, forward, right, up );
// sens al
up = m_pDecals[iDecalIndex].iRndSensX * up;
right = m_pDecals[iDecalIndex].iRndSensY * right;
const float largeur = DECALS_LARGEUR / 2;
int modelindex;
struct model_s *mod = gEngfuncs.CL_LoadModel( m_pDecals[iDecalIndex].model, &modelindex );
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)mod, frame ); //chargement du sprite
if ( m_pDecals[iDecalIndex].flags & ( FLAG_DECAL_DISK | FLAG_DECAL_SG | FLAG_DECAL_XENO ) )
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); //mode de transparence
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //(des)activer le face culling
float timeleft = m_pDecals[iDecalIndex].deathtime - gHUD.m_flTime;
float alpha = timeleft <= 0.5 ? timeleft * 2 : 1.0;
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha );
}
else if ( m_pDecals[iDecalIndex].flags & FLAG_DECAL_XENO )
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); //mode de transparence
gEngfuncs.pTriAPI->CullFace( TRI_FRONT ); //(des)activer le face culling
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 0.6 );
}
else
{
gEngfuncs.pTriAPI->RenderMode( kRenderTransColor ); //mode de transparence
if ( m_pDecals[iDecalIndex].flags & (FLAG_DECAL_WIDEGLASS|FLAG_DECAL_CROWBAR|FLAG_DECAL_CROWBAR_INVERT) )
gEngfuncs.pTriAPI->CullFace( TRI_NONE );
else
gEngfuncs.pTriAPI->CullFace( TRI_FRONT ); //(des)activer le face culling
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
}
gEngfuncs.pTriAPI->Begin( TRI_QUADS ); //d
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); //premier vertex
vertex = m_pDecals[iDecalIndex].origin - ( up + right ) * largeur;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); //deuxieme vertex
vertex = m_pDecals[iDecalIndex].origin + ( right - up ) * largeur;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); //troisieme vertex
vertex = m_pDecals[iDecalIndex].origin + ( right + up ) * largeur;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); //quatrieme vertex
vertex = m_pDecals[iDecalIndex].origin + ( up - right ) * largeur;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->End(); //fin du trac
gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
}
//controle du nombre de quads dessin
// gEngfuncs.Con_Printf ( "client.dll : particules %i quads\n", iresult );
// gEngfuncs.Con_Printf ( "client.dll : decals : %i quads\n", idecalresult );
}
DECLARE_MESSAGE(m_Particules, ClientDecal); //modif de Julien 7/7/01
//
//
// initialisation au chargement de la dll
//
int CHudParticules :: Init( void )
{
for ( int i = 0; i < MAX_PARTICULES ; i ++ )
{
RemoveParticule ( i );
}
for ( int i = 0; i < MAX_DECALS ; i ++ )
{
RemoveDecal ( i );
}
HOOK_MESSAGE(ClientDecal); //modif de Julien npopopoy gvzakdsupp
m_iFlags |= HUD_ACTIVE;
gHUD.AddHudElem(this);
return 1;
}
//
//
// initialisation apr
//
int CHudParticules :: VidInit( void )
{
for ( int i = 0; i < MAX_PARTICULES ; i ++ )
{
RemoveParticule ( i );
}
for ( int i = 0; i < MAX_DECALS ; i ++ )
{
RemoveDecal ( i );
}
m_iFlags |= HUD_ACTIVE;
return 1;
}
//
// activation du syst
// et de particules
// depuis le serveur
//
int CHudParticules::MsgFunc_ClientDecal( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
Vector vecSrc, vecNormal;
char chTextureType;
vecSrc.x = READ_COORD();
vecSrc.y = READ_COORD();
vecSrc.z = READ_COORD();
vecNormal.x = READ_COORD();
vecNormal.y = READ_COORD();
vecNormal.z = READ_COORD();
chTextureType = READ_CHAR();
int decal = READ_BYTE();
if ( decal == 4 ) // explo electro-roquette
{
AddDecal ( vecSrc, Vector ( 90,0,0 ), "sprites/rpg_disk.spr", gHUD.m_flTime + ELECTRO_DISK_MAX / ELECTRO_DISK_SPEED + 0.5, FLAG_DECAL_DISK );
return 1;
}
if ( decal == 5 ) // explo supergun
{
Vector angDir;
VectorAngles ( -vecNormal, angDir );
angDir.y += 180;
AddDecal ( vecSrc, angDir, "sprites/rpg_disk.spr", gHUD.m_flTime + 0.5, FLAG_DECAL_SG );
return 1;
}
if ( decal == 6 ) // muzzle outro
{
Vector vecDir = vecNormal, velocity (0,0,0), avelocity(0,0,0), src = vecSrc;
float largeur, brightness;
//gros
for ( int j=0; j<4; j++ )
{
avelocity = Vector (0.0f, 0.0f, gEngfuncs.pfnRandomFloat(30,60)* ((j%2)==0?1:-1) );
velocity = Vector (vecDir - vecSrc) * 0/*( 0.08 - j*0.02 )*/;
largeur = 5;
brightness = 0.3;
AddParticule ( src, Vector (largeur,brightness,0.0f), velocity, avelocity , "sprites/outro_muzzle.spr", gHUD.m_flTime + 7, FLAG_PARTICULE_OUTRO1 );
}
// petits
for ( int i=0; i<10; i++ )
{
brightness = 0.3;
avelocity = Vector (0.0f, 0.0f, gEngfuncs.pfnRandomFloat(-300,300) );
// velocity = Vector (vecDir - vecSrc) * ( 0.3 - i*0.03 ) * 2.5;
velocity = Vector (vecDir - vecSrc).Normalize() * 0.1;
largeur = 1.2 + i*0.3;
src = vecSrc + 0.1*(vecDir-vecSrc);
AddParticule ( src, Vector (largeur,brightness,0.0f), velocity, avelocity, "sprites/outro_muzzle.spr", gHUD.m_flTime + 7, FLAG_PARTICULE_OUTRO2 );
}
return 1;
}
EV_HLDM_EjectParticules ( vecSrc, vecNormal, chTextureType, decal, 1 );
return 1;
}
/*
message du serveur
MESSAGE_BEGIN( MSG_ALL, gmsgClientDecal );
WRITE_COORD( vecSrc.x ); // xyz source
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_COORD( pTrace->vecPlaneNormal.x ); // xyz norme
WRITE_COORD( pTrace->vecPlaneNormal.y );
WRITE_COORD( pTrace->vecPlaneNormal.z );
WRITE_CHAR ( chTextureType ); // type de texture
MESSAGE_END();
*/