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.
613 lines
12 KiB
613 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; |
|
} |
|
|
|
|