diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index eca8ad0c..80e6ed79 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -3623,7 +3623,7 @@ triangleapi_t gTriApi = static efx_api_t gEfxApi = { R_AllocParticle, - CL_BlobExplosion, + R_BlobExplosion, R_Blood, CL_BloodSprite, R_BloodStream, @@ -3644,8 +3644,8 @@ static efx_api_t gEfxApi = CL_MuzzleFlash, R_ParticleBox, R_ParticleBurst, - CL_ParticleExplosion, - CL_ParticleExplosion2, + R_ParticleExplosion, + R_ParticleExplosion2, R_ParticleLine, CL_PlayerSprites, CL_Projectile, @@ -3692,7 +3692,7 @@ static efx_api_t gEfxApi = CL_TempEntAllocNoModel, CL_TempEntAllocHigh, CL_TempEntAllocCustom, - CL_GetPackedColor, + R_GetPackedColor, R_LookupColor, CL_DecalRemoveAll, CL_FireCustomDecal, diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 7918e1b1..e08e4c83 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -761,6 +761,7 @@ void CL_WritePacket( void ) // update size counter for netgraph cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].sendsize = MSG_GetNumBytesWritten( &buf ); + cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].heldback = false; // composite the rest of the datagram.. if( MSG_GetNumBitsWritten( &cls.datagram ) <= MSG_GetNumBitsLeft( &buf )) diff --git a/engine/client/cl_netgraph.c b/engine/client/cl_netgraph.c index 7eba7d42..b1c3409c 100644 --- a/engine/client/cl_netgraph.c +++ b/engine/client/cl_netgraph.c @@ -20,17 +20,19 @@ GNU General Public License for more details. #define NET_TIMINGS 1024 #define NET_TIMINGS_MASK (NET_TIMINGS - 1) #define LATENCY_AVG_FRAC 0.5 +#define FRAMERATE_AVG_FRAC 0.5 #define PACKETLOSS_AVG_FRAC 0.5 #define PACKETCHOKE_AVG_FRAC 0.5 #define NETGRAPH_LERP_HEIGHT 24 +#define NETGRAPH_NET_COLORS 5 #define NUM_LATENCY_SAMPLES 8 convar_t *net_graph; convar_t *net_graphpos; convar_t *net_graphwidth; convar_t *net_graphheight; +convar_t *net_graphsolid; convar_t *net_scale; -convar_t *net_graphfillsegments; static struct packet_latency_t { @@ -45,30 +47,58 @@ static struct cmdinfo_t qboolean sent; } netstat_cmdinfo[NET_TIMINGS]; -static byte netcolors[NETGRAPH_LERP_HEIGHT+5][4] = +static byte netcolors[NETGRAPH_NET_COLORS+NETGRAPH_LERP_HEIGHT][4] = { - { 255, 0, 0, 255 }, { 0, 0, 255, 255 }, + { 255, 0, 0, 255 }, { 240, 127, 63, 255 }, { 255, 255, 0, 255 }, { 63, 255, 63, 150 } // other will be generated through NetGraph_InitColors() }; +static byte sendcolor[4] = { 88, 29, 130, 255 }; +static byte holdcolor[4] = { 255, 0, 0, 200 }; +static byte extrap_base_color[4] = { 255, 255, 255, 255 }; static netbandwidthgraph_t netstat_graph[NET_TIMINGS]; static float packet_loss; static float packet_choke; +static float framerate = 0.0; +static int maxmsgbytes = 0; /* ========== -NetGraph_DrawLine +NetGraph_DrawRect -CL_FillRGBA shortcut +NetGraph_FillRGBA shortcut ========== */ static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] ) { - CL_FillRGBA( rect->left, rect->top, rect->right, rect->bottom, colors[0], colors[1], colors[2], colors[3] ); + pglColor4ubv( colors ); // color for this quad + + pglVertex2f( rect->left, rect->top ); + pglVertex2f( rect->left + rect->right, rect->top ); + pglVertex2f( rect->left + rect->right, rect->top + rect->bottom ); + pglVertex2f( rect->left, rect->top + rect->bottom ); +} + +/* +========== +NetGraph_AtEdge + +edge detect +========== +*/ +qboolean NetGraph_AtEdge( int x, int width ) +{ + if( x > 3 ) + { + if( x >= width - 4 ) + return true; + return false; + } + return true; } /* @@ -80,21 +110,47 @@ init netgraph colors */ void NetGraph_InitColors( void ) { - int i; - + byte mincolor[2][3]; + byte maxcolor[2][3]; + float dc[2][3]; + int i, hfrac; + float f; + + mincolor[0][0] = 63; + mincolor[0][1] = 0; + mincolor[0][2] = 100; + + maxcolor[0][0] = 0; + maxcolor[0][1] = 63; + maxcolor[0][2] = 255; + + mincolor[1][0] = 255; + mincolor[1][1] = 127; + mincolor[1][2] = 0; + + maxcolor[1][0] = 250; + maxcolor[1][1] = 0; + maxcolor[1][2] = 0; + + for( i = 0; i < 3; i++ ) + { + dc[0][i] = (float)(maxcolor[0][i] - mincolor[0][i]); + dc[1][i] = (float)(maxcolor[1][i] - mincolor[1][i]); + } + + hfrac = NETGRAPH_LERP_HEIGHT / 3; + for( i = 0; i < NETGRAPH_LERP_HEIGHT; i++ ) { - if( i <= NETGRAPH_LERP_HEIGHT / 3 ) + if( i < hfrac ) { - netcolors[i + 5][0] = i * -7.875f + 63; - netcolors[i + 5][1] = i * 7.875f; - netcolors[i + 5][2] = i * 19.375f + 100; + f = (float)i / (float)hfrac; + VectorMA( mincolor[0], f, dc[0], netcolors[NETGRAPH_NET_COLORS + i] ); } else { - netcolors[i + 5][0] = ( i - 8 ) * -0.3125f + 255; - netcolors[i + 5][1] = ( i - 8 ) * -7.9375f + 127; - netcolors[i + 5][2] = 0; + f = (float)(i - hfrac) / (float)(NETGRAPH_LERP_HEIGHT - hfrac ); + VectorMA( mincolor[1], f, dc[1], netcolors[NETGRAPH_NET_COLORS + i] ); } } } @@ -106,14 +162,23 @@ NetGraph_GetFrameData get frame data info, like chokes, packet losses, also update graph, packet and cmdinfo ========== */ -void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_count ) +void NetGraph_GetFrameData( float *latency, int *latency_count ) { - int i, choke_count = 0, loss_count = 0; - float loss, choke; + int i, choke_count = 0, loss_count = 0; + double newtime = Sys_DoubleTime(); + static double nexttime = 0; + float loss, choke; - *biggest_message = *latency_count = 0; + *latency_count = 0; *latency = 0.0f; + if( newtime >= nexttime ) + { + // soft fading of net peak usage + maxmsgbytes = Q_max( 0, maxmsgbytes - 50 ); + nexttime = newtime + 0.05; + } + for( i = cls.netchan.incoming_sequence - CL_UPDATE_BACKUP + 1; i <= cls.netchan.incoming_sequence; i++ ) { frame_t *f = cl.frames + ( i & CL_UPDATE_MASK ); @@ -121,8 +186,7 @@ void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_c netbandwidthgraph_t *g = netstat_graph + ( i & NET_TIMINGS_MASK ); p->choked = f->receivedtime == -2.0f ? true : false; - if( p->choked ) - choke_count++; + if( p->choked ) choke_count++; if( !f->valid ) { @@ -144,17 +208,20 @@ void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_c if( i > cls.netchan.incoming_sequence - NUM_LATENCY_SAMPLES ) { - *latency += 1000.0f * f->latency; - latency_count++; + (*latency) += 1000.0f * f->latency; + (*latency_count)++; } } memcpy( g, &f->graphdata, sizeof( netbandwidthgraph_t )); - if( *biggest_message < g->msgbytes ) - *biggest_message = g->msgbytes; + if( g->msgbytes > maxmsgbytes ) + maxmsgbytes = g->msgbytes; } + if( maxmsgbytes > 1000 ) + maxmsgbytes = 1000; + for( i = cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP + 1; i <= cls.netchan.outgoing_sequence; i++ ) { netstat_cmdinfo[i & NET_TIMINGS_MASK].cmd_lerp = cl.commands[i & CL_UPDATE_MASK].frame_lerp; @@ -180,12 +247,9 @@ NetGraph_DrawTimes void NetGraph_DrawTimes( wrect_t rect, int x, int w ) { int i, j, extrap_point = NETGRAPH_LERP_HEIGHT / 3, a, h; - POINT pt = { Q_max( x + w - 1 - 25, 1 ), Q_max( rect.top + rect.bottom - 4 - NETGRAPH_LERP_HEIGHT + 1, 1 ) }; rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; wrect_t fill; - Con_DrawString( pt.x, pt.y, va( "%i/s", cl_cmdrate->value ), colors ); - for( a = 0; a < w; a++ ) { i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK; @@ -202,10 +266,15 @@ void NetGraph_DrawTimes( wrect_t rect, int x, int w ) h -= extrap_point; fill.top -= extrap_point; + if( !net_graphsolid->value ) + { + fill.top -= (h - 1); + start = (h - 1); + } + for( j = start; j < h; j++ ) { - memcpy( colors, netcolors[j + extrap_point], sizeof( byte ) * 3 ); - NetGraph_DrawRect( &fill, colors ); + NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + extrap_point] ); fill.top--; } } @@ -216,40 +285,60 @@ void NetGraph_DrawTimes( wrect_t rect, int x, int w ) fill.top -= h; h = extrap_point - h; + if( !net_graphsolid->value ) + h = 1; + for( j = 0; j < h; j++ ) { - memcpy( colors, netcolors[j + oldh], sizeof( byte ) * 3 ); - NetGraph_DrawRect( &fill, colors ); + NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + oldh] ); fill.top--; } } fill.top = rect.top + rect.bottom - 4 - extrap_point; - CL_FillRGBA( fill.left, fill.top, fill.right, fill.bottom, 255, 255, 255, 255 ); + if( NetGraph_AtEdge( a, w )) + NetGraph_DrawRect( &fill, extrap_base_color ); - fill.top = rect.top + rect.bottom - 3; + fill.top = rect.top + rect.bottom - 4; - if( !netstat_cmdinfo[i].sent ) - CL_FillRGBA( fill.left, fill.top, fill.right, fill.bottom, 255, 0, 0, 255 ); + if( netstat_cmdinfo[i].sent ) + NetGraph_DrawRect( &fill, sendcolor ); + else NetGraph_DrawRect( &fill, holdcolor ); } } +//left = x +//right = width +//top = y +//bottom = height + /* =========== NetGraph_DrawHatches =========== */ -void NetGraph_DrawHatches( int x, int y, int maxmsgbytes ) +void NetGraph_DrawHatches( int x, int y ) { - int ystep = max((int)( 10.0 / net_scale->value ), 1 ); + int ystep = (int)( 10.0f / net_scale->value ); + byte colorminor[4] = { 0, 63, 63, 200 }; + byte color[4] = { 0, 200, 0, 255 }; wrect_t hatch = { x, 4, y, 1 }; int starty; + ystep = Q_max( ystep, 1 ); + for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale->value < (maxmsgbytes + 50)); hatch.top -= ystep ) { - CL_FillRGBA( hatch.left, hatch.top, hatch.right, hatch.bottom, 63, 63, 0, 200 ); + if(!((int)((starty - hatch.top) * net_scale->value ) % 50 )) + { + NetGraph_DrawRect( &hatch, color ); + } + else if( ystep > 5 ) + { + NetGraph_DrawRect( &hatch, colorminor ); + } } } @@ -259,28 +348,68 @@ NetGraph_DrawTextFields =========== */ -void NetGraph_DrawTextFields( int x, int y, int count, float avg, int packet_loss, int packet_choke ) +void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke ) { static int lastout; rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; - int i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK; - float latency = count > 0 ? Q_max( 0, avg / count - 0.5 * host.frametime - 1000.0 / cl_updaterate->value ) : 0; - float framerate = 1.0 / host.frametime; + int ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 ); + int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 ); + int out, i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK; + int j = cls.netchan.incoming_sequence & NET_TIMINGS_MASK; + int last_y = y - net_graphheight->value; - Con_DrawString( x, y - net_graphheight->value, va( "%.1f fps" , framerate ), colors ); - Con_DrawString( x + 75, y - net_graphheight->value, va( "%i ms" , (int)latency ), colors ); - Con_DrawString( x + 150, y - net_graphheight->value, va( "%i/s" , cl_updaterate->value ), colors ); + if( count > 0 ) + { + avg = avg / (float)( count - ( host.frametime * FRAMERATE_AVG_FRAC )); - if( netstat_cmdinfo[i].size ) - lastout = netstat_cmdinfo[i].size; + if( cl_updaterate->value > 0.0f ) + avg -= 1000.0f / cl_updaterate->value; - Con_DrawString( x, y - net_graphheight->value + 15, va( "in : %i %.2f k/s", netstat_graph[i].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors ); + // can't be below zero + avg = Q_max( 0.0, avg ); + } + else avg = 0.0; - Con_DrawString( x, y - net_graphheight->value + 30, va( "out: %i %.2f k/s", lastout, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); + // move rolling average + framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0 - FRAMERATE_AVG_FRAC ) * framerate; + Con_SetFont( 0 ); - if( net_graph->value > 2 ) - Con_DrawString( x, y - net_graphheight->value + 45, va( "loss: %i choke: %i", packet_loss, packet_choke ), colors ); + if( framerate > 0.0f ) + { + y -= net_graphheight->value; + Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors ); + + if( avg > 1.0f ) + Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors ); + + y += 15; + + out = netstat_cmdinfo[i].size; + if( !out ) out = lastout; + else lastout = out; + + Con_DrawString( x, y, va( "in : %i %.2f k/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors ); + y += 15; + + Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); + y += 15; + + if( net_graph->value > 2 ) + { + int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01 ); + int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01 ); + + Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors ); + } + } + + if( net_graph->value < 3 ) + Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors ); + + Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors ); + + Con_RestoreFont(); } /* @@ -291,13 +420,13 @@ NetGraph_DrawDataSegment */ int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a ) { - int h = bytes / net_scale->value; - byte colors[4] = { r, g, b, a }; + float h = bytes / net_scale->value; + byte colors[4] = { r, g, b, a }; - fill->top -= h; + fill->top -= (int)h; - if( net_graphfillsegments->value ) - fill->bottom = h; + if( net_graphsolid->value ) + fill->bottom = (int)h; else fill->bottom = 1; if( fill->top > 1 ) @@ -305,6 +434,7 @@ int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, NetGraph_DrawRect( fill, colors ); return 1; } + return 0; } @@ -350,9 +480,10 @@ NetGraph_DrawDataUsage =========== */ -void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes ) +void NetGraph_DrawDataUsage( int x, int y, int w ) { int a, i, h, lastvalidh = 0, ping; + int pingheight = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2; wrect_t fill = { 0 }; byte color[4]; @@ -366,31 +497,53 @@ void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes ) if( !ping ) h = lastvalidh; else lastvalidh = h; - if( h > net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2 ) - h = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2; + if( h > pingheight ) + h = pingheight; fill.left = x + w - a - 1; fill.top = y - h; fill.right = 1; fill.bottom = ping ? 1: h; - NetGraph_DrawRect( &fill, color ); + if( !ping ) + { + if( fill.bottom > 3 ) + { + fill.bottom = 2; + NetGraph_DrawRect( &fill, color ); + fill.top += fill.bottom - 2; + NetGraph_DrawRect( &fill, color ); + } + else + { + NetGraph_DrawRect( &fill, color ); + } + } + else + { + NetGraph_DrawRect( &fill, color ); + } fill.top = y; fill.bottom = 1; - color[0] = 0; color[1] = 255; color[2] = 0; color[3] = 160; + color[0] = 0; + color[1] = 255; + color[2] = 0; + color[3] = 160; - NetGraph_DrawRect( &fill, color ); + if( NetGraph_AtEdge( a, w )) + NetGraph_DrawRect( &fill, color ); if( net_graph->value < 2 ) continue; + color[0] = color[1] = color[2] = color[3] = 255; fill.top = y - net_graphheight->value - 1; fill.bottom = 1; - color[0] = color[1] = color[2] = color[3] = 255; - NetGraph_DrawRect( &fill, color ); + if( NetGraph_AtEdge( a, w )) + NetGraph_DrawRect( &fill, color ); fill.top -= 1; @@ -418,21 +571,19 @@ void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes ) if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].usr, 200, 200, 200, 128 )) continue; - // special case for absolute usage - h = netstat_graph[i].msgbytes / net_scale->value; - - color[0] = color[1] = color[2] = 240; color[3] = 255; + if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].voicebytes, 255, 255, 255, 255 )) + continue; + fill.top = y - net_graphheight->value - 1; fill.bottom = 1; - fill.top = y - net_graphheight->value - 1 - h; + fill.top -= 2; - if( fill.top < 2 ) continue; - - NetGraph_DrawRect( &fill, color ); + if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].msgbytes, 240, 240, 240, 128 )) + continue; } if( net_graph->value >= 2 ) - NetGraph_DrawHatches( x, y - net_graphheight->value - 1, maxmsgbytes ); + NetGraph_DrawHatches( x, y - net_graphheight->value - 1 ); } /* @@ -479,7 +630,6 @@ void SCR_DrawNetGraph( void ) wrect_t rect; float avg_ping; int ping_count; - int maxmsgbytes; int w, x, y; if( !host.developer ) @@ -496,15 +646,27 @@ void SCR_DrawNetGraph( void ) NetGraph_GetScreenPos( &rect, &w, &x, &y ); - NetGraph_GetFrameData( &maxmsgbytes, &avg_ping, &ping_count ); + NetGraph_GetFrameData( &avg_ping, &ping_count ); + + NetGraph_DrawTextFields( x, y, w, rect, ping_count, avg_ping, packet_loss, packet_choke ); if( net_graph->value < 3 ) { - NetGraph_DrawTimes( rect, x, w ); - NetGraph_DrawDataUsage( x, y, w, maxmsgbytes ); - } + pglEnable( GL_BLEND ); + pglDisable( GL_TEXTURE_2D ); + pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + pglBegin( GL_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons - NetGraph_DrawTextFields( x, y, ping_count, avg_ping, packet_loss, packet_choke ); + // NOTE: fill colors without texture at this point + NetGraph_DrawDataUsage( x, y, w ); + NetGraph_DrawTimes( rect, x, w ); + + pglEnd(); + pglColor4ub( 255, 255, 255, 255 ); + pglEnable( GL_TEXTURE_2D ); + pglDisable( GL_BLEND ); + } } void CL_InitNetgraph( void ) @@ -514,7 +676,7 @@ void CL_InitNetgraph( void ) net_scale = Cvar_Get( "net_scale", "5", FCVAR_ARCHIVE, "network usage graph scale level" ); net_graphwidth = Cvar_Get( "net_graphwidth", "192", FCVAR_ARCHIVE, "network usage graph width" ); net_graphheight = Cvar_Get( "net_graphheight", "64", FCVAR_ARCHIVE, "network usage graph height" ); - net_graphfillsegments = Cvar_Get( "net_graphfillsegments", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" ); + net_graphsolid = Cvar_Get( "net_graphsolid", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" ); packet_loss = packet_choke = 0.0; NetGraph_InitColors(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index aab27531..38352d72 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1865,7 +1865,8 @@ void CL_ParseServerMessage( sizebuf_t *msg ) } } - cls_message_debug.parsing = false; // done + cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - starting_count; + cls_message_debug.parsing = false; // done // we don't know if it is ok to save a demo message until // after we have parsed the frame diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 9d6cd268..da6b9f4e 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -41,6 +41,7 @@ TEMPENTITY *cl_active_tents; TEMPENTITY *cl_free_tents; TEMPENTITY *cl_tempents = NULL; // entities pool int cl_muzzleflash[MAX_MUZZLEFLASH]; // muzzle flashes +model_t *cl_particleTex = NULL; /* ================ @@ -57,6 +58,7 @@ void CL_RegisterMuzzleFlashes( void ) // update registration for shellchrome cls.hChromeSprite = pfnSPR_Load( "sprites/shellchrome.spr" ); + cl_particleTex = Mod_Handle( CL_FindModelIndex( "sprites/dot.spr" )); } /* @@ -1914,7 +1916,7 @@ void CL_ParseTempEntity( sizebuf_t *msg ) pos[0] = MSG_ReadCoord( &buf ); pos[1] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf ); - CL_BlobExplosion( pos ); + R_BlobExplosion( pos ); break; case TE_SMOKE: pos[0] = MSG_ReadCoord( &buf ); @@ -1959,7 +1961,7 @@ void CL_ParseTempEntity( sizebuf_t *msg ) pos[2] = MSG_ReadCoord( &buf ); color = MSG_ReadByte( &buf ); count = MSG_ReadByte( &buf ); - CL_ParticleExplosion2( pos, color, count ); + R_ParticleExplosion2( pos, color, count ); break; case TE_BSPDECAL: pos[0] = MSG_ReadCoord( &buf ); diff --git a/engine/client/cl_tent.h b/engine/client/cl_tent.h index e59bbe83..4ebead3a 100644 --- a/engine/client/cl_tent.h +++ b/engine/client/cl_tent.h @@ -19,12 +19,12 @@ GNU General Public License for more details. // EfxAPI struct particle_s *R_AllocParticle( void (*callback)( struct particle_s*, float )); void CL_Explosion( vec3_t pos, int model, float scale, float framerate, int flags ); -void CL_ParticleExplosion( const vec3_t org ); -void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ); +void R_ParticleExplosion( const vec3_t org ); +void R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ); void R_Implosion( const vec3_t end, float radius, int count, float life ); void R_Blood( const vec3_t org, const vec3_t dir, int pcolor, int speed ); void R_BloodStream( const vec3_t org, const vec3_t dir, int pcolor, int speed ); -void CL_BlobExplosion( const vec3_t org ); +void R_BlobExplosion( const vec3_t org ); void R_EntityParticles( cl_entity_t *ent ); void R_FlickerParticles( const vec3_t org ); void R_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int count ); @@ -33,7 +33,7 @@ void R_LavaSplash( const vec3_t org ); void R_TeleportSplash( const vec3_t org ); void R_RocketTrail( vec3_t start, vec3_t end, int type ); short R_LookupColor( byte r, byte g, byte b ); -void CL_GetPackedColor( short *packed, short color ); +void R_GetPackedColor( short *packed, short color ); void R_TracerEffect( const vec3_t start, const vec3_t end ); void R_UserTracerParticle( float *org, float *vel, float life, int colorIndex, float length, byte deathcontext, void (*deathfunc)( struct particle_s* )); struct particle_s *R_TracerParticles( float *org, float *vel, float life ); @@ -114,4 +114,6 @@ void TriRenderMode( int mode ); void TriCullFace( int mode ); void TriEnd( void ); +extern model_t *cl_particleTex; + #endif//CL_TENT_H \ No newline at end of file diff --git a/engine/client/client.h b/engine/client/client.h index b71c5e76..a2a9e686 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -622,6 +622,7 @@ extern convar_t *scr_viewsize; extern convar_t *scr_download; extern convar_t *scr_loading; extern convar_t *scr_dark; // start from dark +extern convar_t *net_graph; extern convar_t *rate; //============================================================================= diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index de956301..4ae8e5de 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -407,6 +407,7 @@ void GL_ResetFogColor( void ); void R_SpriteInit( void ); void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ); mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ); +void R_SetSpriteRendermode( const model_t *pModel ); void R_DrawSpriteModel( cl_entity_t *e ); // diff --git a/engine/client/gl_rpart.c b/engine/client/gl_rpart.c index 35961dc2..10ede566 100644 --- a/engine/client/gl_rpart.c +++ b/engine/client/gl_rpart.c @@ -113,12 +113,12 @@ short R_LookupColor( byte r, byte g, byte b ) /* ================ -CL_GetPackedColor +R_GetPackedColor in hardware mode does nothing ================ */ -void CL_GetPackedColor( short *packed, short color ) +void R_GetPackedColor( short *packed, short color ) { if( packed ) *packed = 0; } @@ -139,9 +139,9 @@ void CL_InitParticles( void ) // this is used for EF_BRIGHTFIELD for( i = 0; i < NUMVERTEXNORMALS; i++ ) { - cl_avelocities[i][0] = COM_RandomLong( 0, 255 ) * 0.01f; - cl_avelocities[i][1] = COM_RandomLong( 0, 255 ) * 0.01f; - cl_avelocities[i][2] = COM_RandomLong( 0, 255 ) * 0.01f; + cl_avelocities[i][0] = COM_RandomFloat( 0.0f, 2.55f ); + cl_avelocities[i][1] = COM_RandomFloat( 0.0f, 2.55f ); + cl_avelocities[i][2] = COM_RandomFloat( 0.0f, 2.55f ); } tracerred = Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" ); @@ -360,6 +360,7 @@ void CL_DrawParticles( double frametime ) float grav = frametime * clgame.movevars.gravity * 0.05f; vec3_t right, up; color24 *pColor; + int alpha; float size; if( !cl_draw_particles->value ) @@ -370,13 +371,15 @@ void CL_DrawParticles( double frametime ) if( !cl_active_particles ) return; // nothing to draw? - GL_SetRenderMode( kRenderTransTexture ); - GL_Bind( GL_TEXTURE0, cls.particleImage ); + if( !TriSpriteTexture( cl_particleTex, 0 )) + return; + + R_SetSpriteRendermode( cl_particleTex ); pglBegin( GL_QUADS ); for( p = cl_active_particles; p; p = p->next ) { - if( p->type != pt_blob ) + if(( p->type != pt_blob ) || ( p->packedColor == 255 )) { size = PART_SIZE; // get initial size of particle @@ -386,7 +389,7 @@ void CL_DrawParticles( double frametime ) size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2]; if( size < 20.0f ) size = PART_SIZE; - else size = PART_SIZE + size * 0.004f; + else size = PART_SIZE + size * 0.002f; // scale the axes by radius VectorScale( RI.cull_vright, size, right ); @@ -396,7 +399,11 @@ void CL_DrawParticles( double frametime ) pColor = &clgame.palette[p->color]; // FIXME: should we pass color through lightgamma table? - pglColor4ub( pColor->r, pColor->g, pColor->b, 255 ); + alpha = 255 * (p->die - cl.time) * 2; + if( alpha > 255 || cl_draw_particles->value < 2.0f || p->type == pt_static ) + alpha = 255; + + pglColor4ub( pColor->r, pColor->g, pColor->b, alpha ); pglTexCoord2f( 0.0f, 1.0f ); pglVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] ); @@ -436,17 +443,34 @@ void CL_DrawParticles( double frametime ) p->ramp += time3; if( p->ramp >= 8.0f ) p->die = -1.0f; else p->color = ramp2[(int)p->ramp]; - VectorMA( p->vel,-dvel, p->vel, p->vel ); + VectorMA( p->vel,-frametime, p->vel, p->vel ); p->vel[2] -= grav; break; case pt_blob: + if( p->packedColor == 255 ) + { + // normal blob explosion + VectorMA( p->vel, dvel, p->vel, p->vel ); + p->vel[2] -= grav; + break; + } case pt_blob2: - p->ramp += time2; - if( p->ramp >= 9.0f ) p->ramp = 0.0f; - p->color = gSparkRamp[(int)p->ramp]; - VectorMA( p->vel, -frametime * 0.5f, p->vel, p->vel ); - p->type = COM_RandomLong( 0, 3 ) ? pt_blob : pt_blob2; - p->vel[2] -= grav * 5.0f; + if( p->packedColor == 255 ) + { + // normal blob explosion + p->vel[0] -= p->vel[0] * dvel; + p->vel[1] -= p->vel[1] * dvel; + p->vel[2] -= grav; + } + else + { + p->ramp += time2; + if( p->ramp >= 9.0f ) p->ramp = 0.0f; + p->color = gSparkRamp[(int)p->ramp]; + VectorMA( p->vel, -frametime * 0.5f, p->vel, p->vel ); + p->type = COM_RandomLong( 0, 3 ) ? pt_blob : pt_blob2; + p->vel[2] -= grav * 5.0f; + } break; case pt_grav: p->vel[2] -= grav * 20.0f; @@ -519,6 +543,7 @@ void CL_DrawTracers( double frametime ) float scale, atten, gravity; vec3_t screenLast, screen; vec3_t start, end, delta; + int texWidth = 32; particle_t *p; if( !cl_draw_tracers->value ) @@ -541,13 +566,16 @@ void CL_DrawTracers( double frametime ) if( !cl_active_tracers ) return; // nothing to draw? + if( !TriSpriteTexture( cl_particleTex, 0 )) + return; + + R_SetSpriteRendermode( cl_particleTex ); + R_GetSpriteParms( &texWidth, NULL, NULL, 0, cl_particleTex ); + gravity = frametime * clgame.movevars.gravity; scale = 1.0 - (frametime * 0.9); if( scale < 0.0f ) scale = 0.0f; - GL_Bind( GL_TEXTURE0, cls.particleImage ); // FIXME: load a sprites/dot.spr instead - GL_SetRenderMode( kRenderTransAdd ); - for( p = cl_active_tracers; p; p = p->next ) { atten = (p->die - cl.time); @@ -580,7 +608,7 @@ void CL_DrawTracers( double frametime ) VectorSubtract( normal, tmp2, normal ); // compute four vertexes - VectorScale( normal, gTracerSize[p->type] * 2.0f, tmp ); + VectorScale( normal, gTracerSize[p->type] * (texWidth / 16), tmp ); VectorSubtract( start, tmp, verts[0] ); VectorAdd( start, tmp, verts[1] ); VectorAdd( verts[0], delta, verts[2] ); @@ -663,7 +691,6 @@ void R_EntityParticles( cl_entity_t *ent ) VectorSet( forward, cp * cy, cp * sy, -sp ); p->die = cl.time + 0.001f; - p->type = pt_explode; p->color = 111; // yellow VectorMAMAM( 1.0f, ent->origin, 64.0f, cl_avertexnormals[i], 16.0f, forward, p->org ); @@ -672,11 +699,11 @@ void R_EntityParticles( cl_entity_t *ent ) /* =============== -CL_ParticleExplosion +R_ParticleExplosion =============== */ -void CL_ParticleExplosion( const vec3_t org ) +void R_ParticleExplosion( const vec3_t org ) { particle_t *p; int i, j; @@ -686,38 +713,28 @@ void CL_ParticleExplosion( const vec3_t org ) p = R_AllocParticle( NULL ); if( !p ) return; - p->die += 5.0f; + p->die = cl.time + 5.0f; + p->ramp = COM_RandomLong( 0, 3 ); p->color = ramp1[0]; - p->ramp = rand() & 3; - if( i & 1 ) + for( j = 0; j < 3; j++ ) { - p->type = pt_explode; - for( j = 0; j < 3; j++ ) - { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } - } - else - { - p->type = pt_explode2; - for( j = 0; j < 3; j++ ) - { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } + p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f ); + p->vel[j] = COM_RandomFloat( -256.0f, 256.0f ); } + + if( i & 1 ) p->type = pt_explode; + else p->type = pt_explode2; } } /* =============== -CL_ParticleExplosion2 +R_ParticleExplosion2 =============== */ -void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ) +void R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ) { int i, j; int colorMod = 0; @@ -728,27 +745,28 @@ void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ) p = R_AllocParticle( NULL ); if( !p ) return; - p->die += 0.3f; + p->die = cl.time + 0.3f; p->color = colorStart + ( colorMod % colorLength ); + p->packedColor = 255; // use old code for blob particles colorMod++; p->type = pt_blob; for( j = 0; j < 3; j++ ) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; + p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f ); + p->vel[j] = COM_RandomFloat( -256.0f, 256.0f ); } } } /* =============== -CL_BlobExplosion +R_BlobExplosion =============== */ -void CL_BlobExplosion( const vec3_t org ) +void R_BlobExplosion( const vec3_t org ) { particle_t *p; int i, j; @@ -758,29 +776,24 @@ void CL_BlobExplosion( const vec3_t org ) p = R_AllocParticle( NULL ); if( !p ) return; - p->die += 1.0f + (rand() & 8) * 0.05f; + p->die = cl.time + COM_RandomFloat( 2.0f, 2.4f ); + p->packedColor = 255; // use old code for blob particles if( i & 1 ) { - p->type = pt_explode; - p->color = 66 + rand() % 6; - - for( j = 0; j < 3; j++ ) - { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } + p->type = pt_blob; + p->color = COM_RandomLong( 66, 71 ); } else { - p->type = pt_explode2; - p->color = 150 + rand() % 6; + p->type = pt_blob2; + p->color = COM_RandomLong( 150, 155 ); + } - for( j = 0; j < 3; j++ ) - { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } + for( j = 0; j < 3; j++ ) + { + p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f ); + p->vel[j] = COM_RandomFloat( -256.0f, 256.0f ); } } } @@ -800,7 +813,7 @@ void R_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int cou if( count == 1024 ) { // rocket explosion - CL_ParticleExplosion( org ); + R_ParticleExplosion( org ); return; } diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index ad622a9e..fad0d1da 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -450,6 +450,38 @@ void Mod_UnloadSpriteModel( model_t *mod ) ================ R_GetSpriteFrame +assume pModel is valid +================ +*/ +void R_SetSpriteRendermode( const model_t *pModel ) +{ + msprite_t *psprite; + + if( !pModel ) return; + psprite = (msprite_t *)pModel->cache.data; + if( !psprite ) return; + + switch( psprite->texFormat ) + { + case SPR_NORMAL: + GL_SetRenderMode( kRenderNormal ); + break; + case SPR_ADDITIVE: + GL_SetRenderMode( kRenderTransAdd ); + break; + case SPR_INDEXALPHA: + GL_SetRenderMode( kRenderTransTexture ); + break; + case SPR_ALPHTEST: + GL_SetRenderMode( kRenderTransAlpha ); + break; + } +} + +/* +================ +R_GetSpriteFrame + assume pModel is valid ================ */ diff --git a/engine/common/console.c b/engine/common/console.c index f6b7af01..b85600d9 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -2039,7 +2039,7 @@ void Con_DrawVersion( void ) if( !host.force_draw_version ) { - if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 ) + if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 || net_graph->value ) return; } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index ff06a060..e1af41a8 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -314,6 +314,9 @@ void SV_ActivateServer( void ) // ricochet sprite pfnPrecacheModel( "sprites/richo1.spr" ); + // particle & tracer texture + pfnPrecacheModel( "sprites/dot.spr" ); + // Activate the DLL server code svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.numEntities, svgame.globals->maxClients );