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.

614 lines
12 KiB

//---------------------------------------------------------
//---------------------------------------------------------
//- ---
//- clientlflammes.cpp ---
//- ---
//---------------------------------------------------------
//---------------------------------------------------------
//- code serveur du lance flammes ---
//---------------------------------------------------------
//---------------------------------------------------------
//---------------------------------------------------------
//inclusions
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "parsemsg.h"
#include "triangleapi.h"
#include "cl_entity.h"
extern vec3_t v_angles, v_origin; // angles de la vue du joueur
#define FLAMME_LIBRE 0
#define FLAMME_ATTACHEE 1
#define DETRUIT_FLAMME 2
#define FLAMME_DECO 3
#define FLAMME_DEAD 4
#define FLAMME_FLAMME 0
#define FLAMME_FUMEE 1
#define FLAMME_DYING 2
#define FLAMMES_SPRITE "sprites/lflammes02.spr"
#define FRAMERATE 11
#define MAXFRAMES 33
#define MAXFRAMES_LOOP 21
#define SPRITE_START_WIDTH 4
#define SPRITEFXAMOUNT 180
#define MAX_ROTSPEED 100
#define SPRITE_FADE_TIME 2
#define FLAMME_DECO_WIDTH (SPRITE_START_WIDTH * 28)/2
#define SMOKERATE 0.1
#define FLAMME_DECO_LIFETIME 0.8
#define FLAMME_DECO_FRAMERATE 15
#define FUMEE_SPRITE "sprites/tank_smokeball.spr"
#define FUMEE_MAXFRAMES 7
#define DEAD_LIFETIME 5
#define DEAD_SMOKERATE 0.2
//------------------------------------
//
// d
// gmsgLFlammes
DECLARE_MESSAGE(m_LFlammes, LFlammes );
//------------------------------------
//
// gestion des messages serveur
int CHudLFlammes::MsgFunc_LFlammes( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
int mode = READ_BYTE();
if ( mode == FLAMME_LIBRE || mode == FLAMME_ATTACHEE )
{
int idx = (int)READ_COORD();
float time = READ_COORD();
// nouvelle flamme
flammes_t *p = NULL;
p = new flammes_t;
// param
p->index = idx;
p->flBirthTime = time;
p->bXdir = gEngfuncs.pfnRandomLong(0,1) ? true : false;
p->bYdir = gEngfuncs.pfnRandomLong(0,1) ? true : false;
p->angle = gEngfuncs.pfnRandomFloat ( 0,360 );
p->rotspeed = gEngfuncs.pfnRandomFloat ( -MAX_ROTSPEED, MAX_ROTSPEED );
p->imode = mode;
p->offset.x = READ_COORD();
p->offset.y = READ_COORD();
p->offset.z = READ_COORD();
p->flag = FLAMME_FLAMME;
// pointeur
p->pNext = m_pFlammes;
m_pFlammes = p;
}
else if ( mode == DETRUIT_FLAMME )
{
int idx = (int)READ_COORD();
// destruction d'une flamme
flammes_t *p = NULL;
flammes_t *q = NULL;
p = m_pFlammes;
while ( p != NULL )
{
if ( p->index == idx && p->imode != FLAMME_DECO )
{
if ( q == NULL )
{
// premi
m_pFlammes = p->pNext,
delete p;
break;
}
else
{
q->pNext = p->pNext;
delete p;
break;
}
}
q = p;
p = p->pNext;
}
}
else if ( mode == FLAMME_DEAD )
{
int idx = (int)READ_COORD();
flammes_t *p = NULL;
p = m_pFlammes;
while ( p != NULL )
{
if (p->index == idx && p->imode == FLAMME_ATTACHEE )
{
p->flag = FLAMME_DYING;
p->flBirthTime = gEngfuncs.GetClientTime();
cl_entity_t *ent = gEngfuncs.GetEntityByIndex(gEngfuncs.GetEntityByIndex( p->index )->curstate.aiment);
p->offset = ent->origin;
}
p = p->pNext;
}
}
return 1;
}
//------------------------------------
//
// destruction du registre des flammes
void CHudLFlammes :: ClearFlammes ( void )
{
while ( m_pFlammes != NULL )
{
flammes_t *p = NULL;
p = m_pFlammes;
m_pFlammes = m_pFlammes->pNext;
delete p;
}
}
//------------------------------------
//
// rafraichissement de l'affichage
int CHudLFlammes :: Draw ( float flTime )
{
m_iFlags &= ~HUD_ACTIVE;
return 1;
}
void CHudLFlammes :: DrawFlammes ( void )
{
flammes_t *p = NULL;
p = m_pFlammes;
vec3_t v_forward, v_right, v_up;
// initialisation triapi
int modelindex;
struct model_s *mod = gEngfuncs.CL_LoadModel( FUMEE_SPRITE , &modelindex );
gEngfuncs.pTriAPI->RenderMode( kRenderTransAlpha ); //mode de transparence
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //(des)activer le face culling
// premier cycle pour la fumee
while ( p != NULL )
{
if ( p->flag != FLAMME_FUMEE )
{
p = p->pNext;
continue;
}
float lifetime = gEngfuncs.GetClientTime()-p->flBirthTime;
vec3_t vertex, vecPos;
// position de la flamme
vecPos = p->offset;
// taille du sprite
float fldist;
fldist = FLAMME_DECO_WIDTH;
fldist *= 0.5;
// vecteurs de base
AngleVectors ( v_angles + Vector(0.0f, 0.0f, p->angle ), v_forward, v_right, v_up );
vec3_t right = v_right * fldist * (p->bXdir==true?1:-1);
vec3_t up = v_up * fldist * (p->bYdir==true?1:-1);
p->angle += p->rotspeed * gHUD.m_flTimeDelta;
// frame
int frame;
frame = (int)(lifetime*FLAMME_DECO_FRAMERATE) % FUMEE_MAXFRAMES;
// transparence
float flTrans;
flTrans = 100 * (1- lifetime / FLAMME_DECO_LIFETIME) + 80;
flTrans = flTrans / (float)255;
// trac
gEngfuncs.pTriAPI->Brightness( flTrans );
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, flTrans );
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)mod, frame );
gEngfuncs.pTriAPI->Begin( TRI_QUADS ); //d
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); //premier vertex
vertex = vecPos - right + up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); //deuxieme vertex
vertex = vecPos + right + up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); //troisieme vertex
vertex = vecPos + right - up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); //quatrieme vertex
vertex = vecPos - right - up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->End(); //fin du trac
p = p->pNext;
}
// second cycle pour les flammes
mod = gEngfuncs.CL_LoadModel( FLAMMES_SPRITE , &modelindex );
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); //mode de transparence
p = m_pFlammes;
while ( p != NULL )
{
float lifetime = gEngfuncs.GetClientTime()-p->flBirthTime;
vec3_t vertex, vecPos;
// destruction des flammes trop anciennes
if ( (p->imode == FLAMME_DECO && lifetime > FLAMME_DECO_LIFETIME) /*|| (p->imode == FLAMME_ATTACHEE && p->flag == FLAMME_DYING && lifetime > DEAD_LIFETIME)*/ )
{
flammes_t *r = NULL;
flammes_t *q = NULL;
r = m_pFlammes;
while ( r != NULL )
{
if ( r == p )
{
if ( q == NULL )
{
// premi
m_pFlammes = p->pNext,
delete p;
break;
}
else
{
q->pNext = p->pNext;
delete p;
break;
}
}
q = r;
r = r->pNext;
}
}
// application des vecteurs vitesse
if ( p->imode == FLAMME_DECO )
{
p->offset = p->offset + p->velocity * gHUD.m_flTimeDelta;
}
// position de la flamme
AngleVectors ( v_angles + Vector(0.0f, 0.0f, p->angle ), Vector(0,0,0), v_right, v_up );
if ( p->imode == FLAMME_LIBRE )
vecPos = gEngfuncs.GetEntityByIndex( p->index )->origin;
else if ( p->imode == FLAMME_ATTACHEE && p->flag == FLAMME_DYING )
{
vecPos = p->offset;
}
else if ( p->imode == FLAMME_ATTACHEE )
{
// movetype follow
cl_entity_t *ent = gEngfuncs.GetEntityByIndex(gEngfuncs.GetEntityByIndex( p->index )->curstate.aiment);
vecPos = ent->origin + p->offset;
}
else if ( p->imode == FLAMME_DECO )
vecPos = p->offset;
// apparition des flammes deco
if ( p->imode == FLAMME_ATTACHEE/* && p->flag != FLAMME_ATTACHDEAD*/ )
{
int t1 = lifetime / SMOKERATE;
int t2 = (lifetime-gHUD.m_flTimeDelta) / SMOKERATE;
if ( t2 < t1 )
{
for ( int i=0; i<2; i++ )
{
// g
flammes_t *Q = NULL;
Q = new flammes_t;
// param
Q->index = p->index;
Q->flBirthTime = gEngfuncs.GetClientTime ();
Q->bXdir = gEngfuncs.pfnRandomLong(0,1) ? true : false;
Q->bYdir = gEngfuncs.pfnRandomLong(0,1) ? true : false;
Q->angle = gEngfuncs.pfnRandomFloat ( 0,360 );
Q->rotspeed = gEngfuncs.pfnRandomFloat ( -MAX_ROTSPEED, MAX_ROTSPEED );
Q->imode = FLAMME_DECO;
if ( p->flag == FLAMME_DYING )
{
if ( gEngfuncs.pfnRandomLong( 1, 5 ) == 1 )
Q->flag = FLAMME_FLAMME;
else
Q->flag = FLAMME_FUMEE;
}
else
{
if ( i == 0 )
Q->flag = FLAMME_FLAMME;
else
Q->flag = FLAMME_FUMEE;
}
// physique
Q->offset = vecPos;
Q->velocity = Vector ( gEngfuncs.pfnRandomFloat(-15,15), gEngfuncs.pfnRandomFloat(-15,15), 90.0f );
// pointeur
/* if ( Q->offset == p->offset || Q->offset == vec3_t(0,0,0) || pent == NULL )
{
delete Q;
}
else*/
{
Q->pNext = m_pFlammes;
m_pFlammes = Q;
}
}
}
}
// stop pour la fumee
if ( p->flag == FLAMME_FUMEE )
{
p = p->pNext;
continue;
}
// taille du sprite
float fldist;
if ( p->imode == FLAMME_LIBRE )
{
// y = 0.0837 e (7.712 x )
fldist = lifetime < 0.725 ?
SPRITE_START_WIDTH * ( 1 + 0.0837 * exp( 7.712 * lifetime )) * 32/24 :
SPRITE_START_WIDTH * 28;
}
else if ( p->imode == FLAMME_ATTACHEE )
{
fldist = SPRITE_START_WIDTH * 14;
}
else if ( p->imode == FLAMME_DECO )
{
fldist = FLAMME_DECO_WIDTH;
}
fldist *= 0.5;
// vecteurs de base
vec3_t right = v_right * fldist * (p->bXdir==true?1:-1);
vec3_t up = v_up * fldist * (p->bYdir==true?1:-1);
p->angle += p->rotspeed * gHUD.m_flTimeDelta;
// frame
int frame;
if ( p->imode == FLAMME_LIBRE )
{
frame = (int)(lifetime*FRAMERATE);
frame = frame >= MAXFRAMES ? MAXFRAMES-1 : frame;
}
else if ( p->imode == FLAMME_ATTACHEE )
frame = (int)(lifetime*FRAMERATE) % MAXFRAMES_LOOP;
else if ( p->imode == FLAMME_DECO )
frame = (int)(lifetime*FLAMME_DECO_FRAMERATE) + (MAXFRAMES/FLAMME_DECO_FRAMERATE - FLAMME_DECO_LIFETIME)*FLAMME_DECO_FRAMERATE - 1;
// transparence
float flTrans;
float flratio;
if ( p->imode == FLAMME_ATTACHEE )
{
flTrans = 180;
}
else if ( p->imode == FLAMME_LIBRE )
{
if ( lifetime <= SPRITE_FADE_TIME )
flTrans = 180;
else
{
flratio = (float)(1-(lifetime-(float)SPRITE_FADE_TIME)/(MAXFRAMES/FRAMERATE-SPRITE_FADE_TIME));
flTrans = 180.0;
flTrans *= flratio;
}
}
else if ( p->imode == FLAMME_DECO )
{
flTrans = 100 * (1- lifetime / FLAMME_DECO_LIFETIME) + 80;
}
flTrans = flTrans / (float)255;
// trac
gEngfuncs.pTriAPI->Brightness( flTrans );
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, flTrans );
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)mod, frame );
gEngfuncs.pTriAPI->Begin( TRI_QUADS ); //d
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); //premier vertex
vertex = vecPos - right + up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); //deuxieme vertex
vertex = vecPos + right + up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); //troisieme vertex
vertex = vecPos + right - up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); //quatrieme vertex
vertex = vecPos - right - up;
gEngfuncs.pTriAPI->Vertex3f( vertex.x, vertex.y, vertex.z );
gEngfuncs.pTriAPI->End(); //fin du trac
p = p->pNext;
}
}
//------------------------------------
//
// initialisation au chargement de la dll
int CHudLFlammes :: Init( void )
{
ClearFlammes ();
HOOK_MESSAGE( LFlammes );
m_iFlags |= HUD_ACTIVE;
gHUD.AddHudElem(this);
return 1;
}
//------------------------------------
//
// initialisation apr
int CHudLFlammes :: VidInit( void )
{
ClearFlammes ();
HOOK_MESSAGE( LFlammes );
m_iFlags |= HUD_ACTIVE;
gHUD.AddHudElem(this);
return 1;
}