/* ================= CL_ParseLaser ================= */ static void CL_ParseLaser (sizebuf_t *msg, int colors) { vec3_t start; vec3_t end; laser_t *l; int i; MSG_ReadPos (msg, start); MSG_ReadPos (msg, end); for (i = 0, l = cl_lasers; i < MAX_LASERS; i++, l++) { if (l->endtime < cl.time) { l->ent.flags = RF_TRANSLUCENT | RF_BEAM; VectorCopy (start, l->ent.origin); VectorCopy (end, l->ent.oldorigin); l->ent.alpha = 0.30f; l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff; l->ent.model = NULL; l->ent.frame = 4; l->endtime = cl.time + 100; #ifdef GL_QUAKE AxisClear(l->ent.axis); #endif return; } }
void CL_ParseNuke (void) { vec3_t pos; int32_t i; cl_sustain_t *s, *free_sustain; free_sustain = NULL; for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++) { if (s->id == 0) { free_sustain = s; break; } } if (free_sustain) { s->id = 21000; MSG_ReadPos (&net_message, s->org); s->endtime = cl.time + 1000; s->think = CL_Nukeblast; s->thinkinterval = 1; s->nextthink = cl.time; } else // no free sustains { // FIXME - read the stuff anyway MSG_ReadPos (&net_message, pos); } }
/* ================= CL_ParsePlayerBeam - adds to the cl_playerbeam array instead of the cl_beams array ================= */ int32_t CL_ParsePlayerBeam (struct model_s *model) { int32_t ent; vec3_t start, end, offset; beam_t *b; int32_t i; ent = MSG_ReadShort (&net_message); MSG_ReadPos (&net_message, start); MSG_ReadPos (&net_message, end); // PMM - network optimization if (model == clMedia.mod_heatbeam) VectorSet(offset, 2, 7, -3); else if (model == clMedia.mod_monster_heatbeam) { model = clMedia.mod_heatbeam; VectorSet(offset, 0, 0, 0); } else MSG_ReadPos (&net_message, offset); // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]); // override any beam with the same entity // PMM - For player beams, we only want one per player (entity) so.. for (i=0, b=cl_playerbeams; i<MAX_BEAMS; i++, b++) { if (b->entity == ent) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } } // find a free beam for (i=0, b=cl_playerbeams; i<MAX_BEAMS; i++, b++) { if (!b->model || b->endtime < cl.time) { b->entity = ent; b->model = model; b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } } Com_Printf ("beam list overflow!\n"); return ent; }
/* * adds to the cl_playerbeam array instead of the cl_beams array */ void CL_ParsePlayerBeam ( struct model_s *model ) { q_int32_t ent; vec3_t start, end, offset; beam_t *b; q_int32_t i; ent = MSG_ReadShort ( &net_message ); MSG_ReadPos ( &net_message, start ); MSG_ReadPos ( &net_message, end ); /* network optimization */ if ( model == cl_mod_heatbeam ) { VectorSet ( offset, 2, 7, -3 ); } else if ( model == cl_mod_monster_heatbeam ) { model = cl_mod_heatbeam; VectorSet ( offset, 0, 0, 0 ); } else { MSG_ReadPos ( &net_message, offset ); } /* Override any beam with the same entity For player beams, we only want one per player (entity) so... */ for ( i = 0, b = cl_playerbeams; i < MAX_BEAMS; i++, b++ ) { if ( b->entity == ent ) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorCopy ( offset, b->offset ); return; } } /* find a free beam */ for ( i = 0, b = cl_playerbeams; i < MAX_BEAMS; i++, b++ ) { if ( !b->model || ( b->endtime < cl.time ) ) { b->entity = ent; b->model = model; b->endtime = cl.time + 100; /* this needs to be 100 to prevent multiple heatbeams */ VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorCopy ( offset, b->offset ); return; } } Com_Printf ( "beam list overflow!\n" ); return; }
// Psychspaz's enhanced particles int32_t CL_ParseLightning () { vec3_t start,end; // ,move,vec; int32_t srcEnt, dstEnt; // , len, dec; srcEnt = MSG_ReadShort (&net_message); dstEnt = MSG_ReadShort (&net_message); MSG_ReadPos (&net_message, start); MSG_ReadPos (&net_message, end); CL_LightningBeam(start, end, srcEnt, dstEnt, 5); return srcEnt; }
/* ================= CL_ParseBeam2 ================= */ int32_t CL_ParseBeam2 (struct model_s *model) { int32_t ent; vec3_t start, end, offset; beam_t *b; int32_t i; ent = MSG_ReadShort (&net_message); MSG_ReadPos (&net_message, start); MSG_ReadPos (&net_message, end); MSG_ReadPos (&net_message, offset); // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]); // override any beam with the same entity for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) if (b->entity == ent) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } // find a free beam for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { if (!b->model || b->endtime < cl.time) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } } Com_Printf ("beam list overflow!\n"); return ent; }
/* ================= CL_ParseLightning ================= */ static int CL_ParseLightning (sizebuf_t *msg, struct model_s *model) { int srcEnt, destEnt; vec3_t start, end; beam_t *b; int i; srcEnt = MSG_ReadShort (msg); destEnt = MSG_ReadShort (msg); MSG_ReadPos (msg, start); MSG_ReadPos (msg, end); // override any beam with the same source AND destination entities for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { if (b->entity == srcEnt && b->dest_entity == destEnt) { //b->entity = srcEnt; //b->dest_entity = destEnt; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorClear (b->offset); return srcEnt; } } // find a free beam for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { if (!b->model || b->endtime < cl.time) { b->entity = srcEnt; b->dest_entity = destEnt; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorClear (b->offset); return srcEnt; } } Com_Printf ("beam list overflow!\n"); return srcEnt; }
/* ================= CL_ParseBeam2 ================= */ static int CL_ParseBeam2 (sizebuf_t *msg, struct model_s *model) { int ent; vec3_t start, end, offset; beam_t *b; int i; ent = MSG_ReadShort (msg); MSG_ReadPos (msg, start); MSG_ReadPos (msg, end); MSG_ReadPos (msg, offset); // override any beam with the same entity for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { if (b->entity == ent) { //b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } } // find a free beam for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) { if (!b->model || b->endtime < cl.time) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy (start, b->start); VectorCopy (end, b->end); VectorCopy (offset, b->offset); return ent; } } Com_Printf ("beam list overflow!\n"); return ent; }
/* ========================================================================= */ q_int32_t CL_ParseLightning ( struct model_s *model ) { q_int32_t srcEnt, destEnt; vec3_t start, end; beam_t *b; q_int32_t i; srcEnt = MSG_ReadShort ( &net_message ); destEnt = MSG_ReadShort ( &net_message ); MSG_ReadPos ( &net_message, start ); MSG_ReadPos ( &net_message, end ); /* override any beam with the same source AND destination entities */ for ( i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++ ) { if ( ( b->entity == srcEnt ) && ( b->dest_entity == destEnt ) ) { b->entity = srcEnt; b->dest_entity = destEnt; b->model = model; b->endtime = cl.time + 200; VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorClear ( b->offset ); return srcEnt; } } /* find a free beam */ for ( i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++ ) { if ( !b->model || ( b->endtime < cl.time ) ) { b->entity = srcEnt; b->dest_entity = destEnt; b->model = model; b->endtime = cl.time + 200; VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorClear ( b->offset ); return srcEnt; } } Com_Printf ( "beam list overflow!\n" ); return srcEnt; }
/* ========================================================================= */ void CL_ParseParticles ( void ) { q_int32_t color, count; vec3_t pos, dir; MSG_ReadPos ( &net_message, pos ); MSG_ReadDir ( &net_message, dir ); color = MSG_ReadByte ( &net_message ); count = MSG_ReadByte ( &net_message ); CL_ParticleEffect ( pos, dir, color, count ); }
// Psychspaz's enhanced particles void CL_ParseLaser (int32_t colors) { vec3_t start,end; vec3_t move; vec3_t vec; vec3_t point; float len; float dec; MSG_ReadPos (&net_message, start); MSG_ReadPos (&net_message, end); VectorSubtract (end, start, vec); len = VectorNormalize (vec); VectorCopy (vec, point); dec = 20; VectorScale (vec, dec, vec); VectorCopy (start, move); while (len > 0) { len -= dec; CL_SetupParticle ( point[0], point[1], point[2], move[0], move[1], move[2], 0, 0, 0, 0, 0, 0, 50, 255, 50, 0, 0, 0, 1, -2.5, GL_SRC_ALPHA, GL_ONE, dec*TWOTHIRDS, 0, particle_beam, PART_DIRECTION, NULL,0); VectorAdd (move, vec, move); } }
/* ========================================================================= */ void CL_ParseBeam2 ( struct model_s *model ) { q_int32_t ent; vec3_t start, end, offset; beam_t *b; q_int32_t i; ent = MSG_ReadShort ( &net_message ); MSG_ReadPos ( &net_message, start ); MSG_ReadPos ( &net_message, end ); MSG_ReadPos ( &net_message, offset ); /* override any beam with the same entity */ for ( i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++ ) { if ( b->entity == ent ) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorCopy ( offset, b->offset ); return; } } /* find a free beam */ for ( i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++ ) { if ( !b->model || ( b->endtime < cl.time ) ) { b->entity = ent; b->model = model; b->endtime = cl.time + 200; VectorCopy ( start, b->start ); VectorCopy ( end, b->end ); VectorCopy ( offset, b->offset ); return; } } Com_Printf ( "beam list overflow!\n" ); return; }
/* ========================================================================= */ void CL_ParseLaser ( q_int32_t colors ) { vec3_t start; vec3_t end; laser_t *l; q_int32_t i; MSG_ReadPos ( &net_message, start ); MSG_ReadPos ( &net_message, end ); for ( i = 0, l = cl_lasers; i < MAX_LASERS; i++, l++ ) { if ( l->endtime < cl.time ) { l->ent.flags = RF_TRANSLUCENT | RF_BEAM; VectorCopy ( start, l->ent.origin ); VectorCopy ( end, l->ent.oldorigin ); l->ent.alpha = 0.30f; l->ent.skinnum = ( colors >> ( ( randk() % 4 ) * 8 ) ) & 0xff; l->ent.model = NULL; l->ent.frame = 4; l->endtime = cl.time + 100; return; } }
//============= //ROGUE void CL_ParseSteam (void) { vec3_t pos, dir; int32_t id, i; int32_t r; int32_t cnt; int32_t color; int32_t magnitude; cl_sustain_t *s, *free_sustain; id = MSG_ReadShort (&net_message); // an id of -1 is an instant effect if (id != -1) // sustains { //Com_Printf ("Sustain effect id %d\n", id); free_sustain = NULL; for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++) { if (s->id == 0) { free_sustain = s; break; } } if (free_sustain) { s->id = id; s->count = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, s->org); MSG_ReadDir (&net_message, s->dir); r = MSG_ReadByte (&net_message); s->color = r & 0xff; s->magnitude = MSG_ReadShort (&net_message); s->endtime = cl.time + MSG_ReadLong (&net_message); s->think = CL_ParticleSteamEffect2; s->thinkinterval = 100; s->nextthink = cl.time; } else { //Com_Printf ("No free sustains!\n"); // FIXME - read the stuff anyway cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); r = MSG_ReadByte (&net_message); magnitude = MSG_ReadShort (&net_message); magnitude = MSG_ReadLong (&net_message); // really interval } } else // instant { cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); r = MSG_ReadByte (&net_message); magnitude = MSG_ReadShort (&net_message); color = r & 0xff; CL_ParticleSteamEffect (pos, dir, color8red(color), color8green(color), color8blue(color), -20, -20, -20, cnt, magnitude); //CL_ParticleSteamEffect (pos, dir, 240, 240, 240, -20, -20, -20, cnt, magnitude); //S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); } }
/* ================== CL_ParseDelta Can go from either a baseline or a previous packet_entity ================== */ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits) { // set everything to the state we are delta'ing from *to = *from; VectorCopy(from->origin, to->old_origin); to->number = number; if (bits & U_MODEL) to->modelindex = MSG_ReadByte(&net_message); if (bits & U_MODEL2) to->modelindex2 = MSG_ReadByte(&net_message); if (bits & U_MODEL3) to->modelindex3 = MSG_ReadByte(&net_message); if (bits & U_MODEL4) to->modelindex4 = MSG_ReadByte(&net_message); if (bits & U_FRAME8) to->frame = MSG_ReadByte(&net_message); if (bits & U_FRAME16) to->frame = MSG_ReadShort(&net_message); assert(to->skinnum >= 0); // jitdebug if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors to->skinnum = MSG_ReadLong(&net_message); else if (bits & U_SKIN8) to->skinnum = MSG_ReadByte(&net_message); else if (bits & U_SKIN16) to->skinnum = MSG_ReadShort(&net_message); assert(to->skinnum >= 0); if ((bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16)) to->effects = MSG_ReadLong(&net_message); else if (bits & U_EFFECTS8) to->effects = MSG_ReadByte(&net_message); else if (bits & U_EFFECTS16) to->effects = MSG_ReadShort(&net_message); if ((bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16)) to->renderfx = MSG_ReadLong(&net_message); else if (bits & U_RENDERFX8) to->renderfx = MSG_ReadByte(&net_message); else if (bits & U_RENDERFX16) to->renderfx = MSG_ReadShort(&net_message); if (bits & U_ORIGIN1) to->origin[0] = MSG_ReadCoord(&net_message); if (bits & U_ORIGIN2) to->origin[1] = MSG_ReadCoord(&net_message); if (bits & U_ORIGIN3) to->origin[2] = MSG_ReadCoord(&net_message); if (bits & U_ANGLE1) to->angles[0] = MSG_ReadAngle(&net_message); if (bits & U_ANGLE2) to->angles[1] = MSG_ReadAngle(&net_message); if (bits & U_ANGLE3) to->angles[2] = MSG_ReadAngle(&net_message); if (bits & U_OLDORIGIN) MSG_ReadPos(&net_message, to->old_origin); if (bits & U_SOUND) to->sound = MSG_ReadByte(&net_message); if (bits & U_EVENT) to->event = MSG_ReadByte(&net_message); else to->event = 0; if (bits & U_SOLID) to->solid = MSG_ReadShort(&net_message); }
void CL_ParseTEnt (void) { int32_t type; vec3_t pos, pos2, dir; explosion_t *ex; int32_t cnt; int32_t color; int32_t r, i; int32_t ent; int32_t magnitude; type = MSG_ReadByte (&net_message); switch (type) { case TE_BLOOD: // bullet hitting flesh MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Psychospaz's enhanced particle code CL_BloodHit (pos, dir); break; case TE_GUNSHOT: // bullet hitting wall case TE_SPARKS: case TE_BULLET_SPARKS: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Psychospaz's enhanced particle code if (type == TE_BULLET_SPARKS) VectorScale(dir, 2, dir); { vec3_t color = { 255, 125, 10 }; CL_ParticleEffectSparks (pos, dir, color, (type == TE_GUNSHOT)? 5 : 10); } if (type != TE_SPARKS) { CL_GunSmokeEffect (pos, dir); if (type == TE_GUNSHOT || type == TE_BULLET_SPARKS) CL_ParticleBulletDecal(pos, dir, 2.5); // impact sound cnt = rand()&15; if (cnt == 1) S_StartSound (pos, 0, 0, clMedia.sfx_ric[0], 1, ATTN_NORM, 0); else if (cnt == 2) S_StartSound (pos, 0, 0, clMedia.sfx_ric[1], 1, ATTN_NORM, 0); else if (cnt == 3) S_StartSound (pos, 0, 0, clMedia.sfx_ric[2], 1, ATTN_NORM, 0); } break; case TE_SHOTGUN: // bullet hitting wall MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Psychospaz's enhanced particle code CL_GunSmokeEffect (pos, dir); CL_ParticleBulletDecal(pos, dir, 2.8); { vec3_t color = { 200, 100, 10 }; CL_ParticleEffectSparks (pos, dir, color, 8); } break; case TE_SCREEN_SPARKS: case TE_SHIELD_SPARKS: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); if (type == TE_SCREEN_SPARKS) CL_ParticleEffect (pos, dir, 0xd0, 40); else CL_ParticleEffect (pos, dir, 0xb0, 40); //FIXME : replace or remove this sound S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; case TE_SPLASH: // bullet hitting water cnt = MSG_ReadByte (&net_message); cnt = min(cnt, 40); // cap at 40 MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); r = MSG_ReadByte (&net_message); if (r > 6) color = 0x00; else color = splash_color[r]; // Psychospaz's enhanced particle code if (r == SPLASH_SPARKS) { CL_ParticleEffectSplashSpark (pos, dir, color, cnt); r = rand() & 3; if (r == 0) S_StartSound (pos, 0, 0, clMedia.sfx_spark[0], 1, ATTN_STATIC, 0); else if (r == 1) S_StartSound (pos, 0, 0, clMedia.sfx_spark[1], 1, ATTN_STATIC, 0); else S_StartSound (pos, 0, 0, clMedia.sfx_spark[2], 1, ATTN_STATIC, 0); } else { CL_ParticleEffectSplash (pos, dir, color, cnt); } break; case TE_LASER_SPARKS: cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); color = MSG_ReadByte (&net_message); CL_ParticleEffect2 (pos, dir, color, cnt); break; case TE_RAILTRAIL: // railgun effect MSG_ReadPos (&net_message, pos); MSG_ReadPos (&net_message, pos2); CL_RailTrail (pos, pos2, false); S_StartSound (pos2, 0, 0, clMedia.sfx_railg, 1, ATTN_NORM, 0); break; // 12/23/2001 - red railgun trail case TE_RAILTRAIL2: // red railgun effect MSG_ReadPos (&net_message, pos); MSG_ReadPos (&net_message, pos2); CL_RailTrail (pos, pos2, true); S_StartSound (pos2, 0, 0, clMedia.sfx_railg, 1, ATTN_NORM, 0); break; case TE_EXPLOSION2: case TE_GRENADE_EXPLOSION: case TE_GRENADE_EXPLOSION_WATER: MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW; // noshadow flag ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.model = clMedia.mod_explo; ex->frames = 19; ex->baseframe = 30; ex->ent.angles[1] = rand() % 360; CL_Explosion_Sparks (pos, 16, 128); if (type != TE_EXPLOSION2) CL_Explosion_Decal (pos, 50, particle_burnmark); if (type == TE_GRENADE_EXPLOSION_WATER) S_StartSound (pos, 0, 0, clMedia.sfx_watrexp, 1, ATTN_NORM, 0); else S_StartSound (pos, 0, 0, clMedia.sfx_grenexp, 1, ATTN_NORM, 0); break; // RAFAEL case TE_PLASMA_EXPLOSION: MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW; // noshadow flag ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.angles[1] = rand() % 360; ex->ent.model = clMedia.mod_explo; if (frand() < 0.5) ex->baseframe = 15; ex->frames = 15; CL_Explosion_Sparks (pos, 16, 128); CL_Explosion_Decal (pos, 50, particle_burnmark); if (cl_plasma_explo_sound->value) S_StartSound (pos, 0, 0, clMedia.sfx_plasexp, 1, ATTN_NORM, 0); else S_StartSound (pos, 0, 0, clMedia.sfx_rockexp, 1, ATTN_NORM, 0); break; case TE_EXPLOSION1_BIG: // PMM MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW; // noshadow flag ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.angles[1] = rand() % 360; ex->ent.model = clMedia.mod_explo_big; if (frand() < 0.5) ex->baseframe = 15; ex->frames = 15; CL_Explosion_Sparks (pos, 48, 128); S_StartSound (pos, 0, 0, clMedia.sfx_rockexp, 1, ATTN_NORM, 0); break; case TE_EXPLOSION1_NP: // PMM MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW; // noshadow flag ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.angles[1] = rand() % 360; ex->ent.model = clMedia.mod_explo; if (frand() < 0.5) ex->baseframe = 15; ex->frames = 15; CL_Explosion_Sparks (pos, 10, 128); S_StartSound (pos, 0, 0, clMedia.sfx_grenexp, 1, ATTN_NORM, 0); break; case TE_EXPLOSION1: case TE_PLAIN_EXPLOSION: case TE_ROCKET_EXPLOSION: case TE_ROCKET_EXPLOSION_WATER: MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW; // noshadow flag ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 0.5; ex->lightcolor[2] = 0.5; ex->ent.angles[1] = rand() % 360; ex->ent.model = clMedia.mod_explo; if (frand() < 0.5) ex->baseframe = 15; ex->frames = 15; CL_Explosion_Sparks (pos, 16, 128); if (type == TE_ROCKET_EXPLOSION || type == TE_ROCKET_EXPLOSION_WATER) CL_Explosion_Decal (pos, 50, particle_burnmark); if (type == TE_ROCKET_EXPLOSION_WATER) S_StartSound (pos, 0, 0, clMedia.sfx_watrexp, 1, ATTN_NORM, 0); else S_StartSound (pos, 0, 0, clMedia.sfx_rockexp, 1, ATTN_NORM, 0); break; case TE_BFG_EXPLOSION: MSG_ReadPos (&net_message, pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_poly; ex->ent.flags |= RF_FULLBRIGHT; ex->start = cl.frame.servertime - 100; ex->light = 350; ex->lightcolor[0] = 0.0; ex->lightcolor[1] = 1.0; ex->lightcolor[2] = 0.0; ex->ent.model = clMedia.mod_bfg_explo; ex->ent.flags |= RF_TRANSLUCENT | RF_TRANS_ADDITIVE; ex->ent.alpha = 0.30; ex->frames = 4; break; case TE_BFG_BIGEXPLOSION: MSG_ReadPos (&net_message, pos); CL_BFGExplosionParticles (pos); CL_Explosion_Decal (pos, 75, particle_bfgmark); break; case TE_BFG_LASER: CL_ParseLaser (0xd0d1d2d3); break; case TE_BUBBLETRAIL: MSG_ReadPos (&net_message, pos); MSG_ReadPos (&net_message, pos2); CL_BubbleTrail (pos, pos2); break; case TE_PARASITE_ATTACK: case TE_MEDIC_CABLE_ATTACK: ent = CL_ParseBeam (clMedia.mod_parasite_segment); break; case TE_BOSSTPORT: // boss teleporting to station MSG_ReadPos (&net_message, pos); CL_BigTeleportParticles (pos); S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0); break; case TE_GRAPPLE_CABLE: ent = CL_ParseBeam2 (clMedia.mod_grapple_cable); break; // RAFAEL case TE_WELDING_SPARKS: cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); color = MSG_ReadByte (&net_message); // Psychospaz's enhanced particle code { vec3_t sparkcolor = {color8red(color), color8green(color), color8blue(color)}; CL_ParticleEffectSparks (pos, dir, sparkcolor, 40); } ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->type = ex_flash; // note to self // we need a better no draw flag ex->ent.flags |= RF_BEAM; ex->start = cl.frame.servertime - 0.1; ex->light = 100 + (rand()%75); ex->lightcolor[0] = 1.0; ex->lightcolor[1] = 1.0; ex->lightcolor[2] = 0.3; ex->ent.model = clMedia.mod_flash; ex->frames = 2; break; case TE_GREENBLOOD: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Psychospaz's enhanced particle code CL_GreenBloodHit (pos, dir); break; // RAFAEL case TE_TUNNEL_SPARKS: cnt = MSG_ReadByte (&net_message); MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); color = MSG_ReadByte (&net_message); CL_ParticleEffect3 (pos, dir, color, cnt); break; //============= //PGM // PMM -following code integrated for flechette (different color) case TE_BLASTER: // blaster hitting wall case TE_BLASTER2: // green blaster hitting wall case TE_BLUEHYPERBLASTER: // blue blaster hitting wall case TE_REDBLASTER: // red blaster hitting wall case TE_FLECHETTE: // flechette hitting wall MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); ex = CL_AllocExplosion (); VectorCopy (pos, ex->ent.origin); ex->ent.angles[0] = acos(dir[2])/M_PI*180; if (dir[0]) // PMM - fixed to correct for pitch of 0 ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180; else if (dir[1] > 0) ex->ent.angles[1] = 90; else if (dir[1] < 0) ex->ent.angles[1] = 270; else ex->ent.angles[1] = 0; ex->type = ex_misc; ex->ent.flags |= RF_FULLBRIGHT|RF_TRANSLUCENT|RF_NOSHADOW; // no shadow on these if (type == TE_BLASTER2) ex->ent.skinnum = 1; else if (type == TE_REDBLASTER) ex->ent.skinnum = 3; else if (type == TE_FLECHETTE || type == TE_BLUEHYPERBLASTER) ex->ent.skinnum = 2; else // TE_BLASTER ex->ent.skinnum = 0; ex->start = cl.frame.servertime - 100; ex->light = 150; if (type == TE_BLASTER2) { ex->lightcolor[0] = 0.15; ex->lightcolor[1] = 1; ex->lightcolor[2] = 0.15; } else if (type == TE_BLUEHYPERBLASTER) { ex->lightcolor[0] = 0.19; ex->lightcolor[1] = 0.41; ex->lightcolor[2] = 0.75; } else if (type == TE_REDBLASTER) { ex->lightcolor[0] = 0.75; ex->lightcolor[1] = 0.41; ex->lightcolor[2] = 0.19; } else if (type == TE_FLECHETTE) { ex->lightcolor[0] = 0.39; ex->lightcolor[1] = 0.61; ex->lightcolor[2] = 0.75; } else { // TE_BLASTER ex->lightcolor[0] = 1; ex->lightcolor[1] = 1; ex->lightcolor[2] = 0; } ex->ent.model = clMedia.mod_explode; ex->frames = 4; // Psychospaz's enhanced particle code { int32_t red, green, blue, numparts; float partsize = 4; numparts = (32 / max(cl_particle_scale->value/2, 1)); if (type == TE_BLASTER2) { CL_BlasterParticles (pos, dir, numparts, partsize, 50, 235, 50, -10, 0, -10); red=50; green=235; blue=50; } else if (type == TE_BLUEHYPERBLASTER) { CL_BlasterParticles (pos, dir, numparts, partsize, 50, 50, 235, -10, 0, -10); red=50; green=50; blue=235; } else if (type == TE_REDBLASTER) { CL_BlasterParticles (pos, dir, numparts, partsize, 235, 50, 50, 0, -90, -30); red=235; green=50; blue=50; } else if (type == TE_FLECHETTE) { CL_BlasterParticles (pos, dir, numparts, partsize, 100, 100, 195, -10, 0, -10); red=100; green=100; blue=195; } else { // TE_BLASTER CL_BlasterParticles (pos, dir, numparts, partsize, 255, 150, 50, 0, -90, -30); // was 40 red=255; green=150; blue=50; } CL_ParticleBlasterDecal(pos, dir, 10, red, green, blue); } S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; // shockwave impact effect case TE_SHOCKSPLASH: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Spawn 5 rings for (i = 0; i < 5; i++) { ex = CL_AllocExplosion (); VectorMA (pos, 16.0*(i+1), dir, ex->ent.origin); vectoangles2(dir, ex->ent.angles); //VectorCopy (dir, ex->ent.angles); ex->type = ex_poly2; ex->ent.flags |= RF_FULLBRIGHT|RF_TRANSLUCENT|RF_NOSHADOW; ex->start = cl.frame.servertime - 100; ex->light = 75; ex->lightcolor[0] = 0.39; ex->lightcolor[1] = 0.61; ex->lightcolor[2] = 0.75; ex->ent.model = clMedia.mod_shocksplash; ex->ent.alpha = 0.70; ex->baseframe = 4-i; ex->frames = 4+i; } S_StartSound (pos, 0, 0, clMedia.sfx_shockhit, 1, ATTN_NONE, 0); break; case TE_LIGHTNING: // Psychospaz's enhanced particle code ent = CL_ParseLightning (); S_StartSound (NULL, ent, CHAN_WEAPON, clMedia.sfx_lightning, 1, ATTN_NORM, 0); break; case TE_DEBUGTRAIL: MSG_ReadPos (&net_message, pos); MSG_ReadPos (&net_message, pos2); CL_DebugTrail (pos, pos2); break; case TE_FLASHLIGHT: MSG_ReadPos(&net_message, pos); ent = MSG_ReadShort(&net_message); CL_Flashlight(ent, pos); break; case TE_FORCEWALL: MSG_ReadPos(&net_message, pos); MSG_ReadPos(&net_message, pos2); color = MSG_ReadByte (&net_message); CL_ForceWall(pos, pos2, color); break; case TE_HEATBEAM: ent = CL_ParsePlayerBeam (clMedia.mod_heatbeam); break; case TE_MONSTER_HEATBEAM: ent = CL_ParsePlayerBeam (clMedia.mod_monster_heatbeam); break; case TE_HEATBEAM_SPARKS: cnt = 50; MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); r = 8; magnitude = 60; CL_ParticleSteamEffect (pos, dir, 240, 240, 240, -20, -20, -20, cnt, magnitude); S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; case TE_HEATBEAM_STEAM: cnt = 20; MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); magnitude = 60; CL_ParticleSteamEffect (pos, dir, 255, 150, 50, 0, -90, -30, cnt, magnitude); CL_ParticlePlasmaBeamDecal (pos, dir, 10); // added burnmark S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; case TE_STEAM: CL_ParseSteam(); break; case TE_BUBBLETRAIL2: cnt = 3; // was 8 MSG_ReadPos (&net_message, pos); MSG_ReadPos (&net_message, pos2); CL_BubbleTrail2 (pos, pos2, cnt); S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; case TE_MOREBLOOD: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // Psychospaz's enhanced particle code CL_BloodHit (pos, dir); CL_BloodHit (pos, dir); break; case TE_CHAINFIST_SMOKE: dir[0]=0; dir[1]=0; dir[2]=1; MSG_ReadPos(&net_message, pos); // Psychospaz's enhanced particle code CL_ParticleSmokeEffect (pos, dir, 8); break; case TE_ELECTRIC_SPARKS: MSG_ReadPos (&net_message, pos); MSG_ReadDir (&net_message, dir); // new blue electric sparks CL_ElectricParticles (pos, dir, 40); //FIXME : replace or remove this sound S_StartSound (pos, 0, 0, clMedia.sfx_lashit, 1, ATTN_NORM, 0); break; case TE_TRACKER_EXPLOSION: MSG_ReadPos (&net_message, pos); CL_ColorFlash (pos, 0, 150, -1, -1, -1); // CL_ColorExplosionParticles (pos, 0, 1); CL_Tracker_Explode (pos); CL_Explosion_Decal (pos, 14, particle_trackermark); S_StartSound (pos, 0, 0, clMedia.sfx_disrexp, 1, ATTN_NORM, 0); break; case TE_TELEPORT_EFFECT: case TE_DBALL_GOAL: MSG_ReadPos (&net_message, pos); CL_TeleportParticles (pos); break; case TE_WIDOWBEAMOUT: CL_ParseWidow (); break; case TE_NUKEBLAST: CL_ParseNuke (); break; case TE_WIDOWSPLASH: MSG_ReadPos (&net_message, pos); CL_WidowSplash (pos); break; //PGM //============== default: Com_Error (ERR_DROP, "CL_ParseTEnt: bad type"); } }
sizebuf_t *SV_MulticastHook(sizebuf_t *original, sizebuf_t *ext) { CVec3 v1, v2; const char *s; guard(SV_MulticastHook); original->BeginReading(); // check for interesting messages if (MSG_ReadByte(original) != svc_temp_entity) return original; ext->Clear(); byte cmd = MSG_ReadByte(original); switch (cmd) { case TE_RAILTRAIL: { MSG_ReadPos(original, v1); // start MSG_ReadPos(original, v2); // end client_t *cl = FindClient(v1, 18*18); int rType = 1; int rColor = 0; if (cl) { if (s = Info_ValueForKey(cl->Userinfo, "railcolor")) { rColor = atoi(s); rColor = bound(rColor, 0, 7); } if (s = Info_ValueForKey(cl->Userinfo, "railtype")) { rType = atoi(s); rType = bound(rType, 0, 3); } } if (!rType) return original; // type==0 -> original rail trail MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, TE_RAILTRAIL_EXT); MSG_WritePos(ext, v1); MSG_WritePos(ext, v2); MSG_WriteByte(ext, rColor); MSG_WriteByte(ext, rType); } return ext; case TE_GUNSHOT: case TE_SPARKS: case TE_BULLET_SPARKS: { if (shotLevel != 2) return original; MSG_ReadPos(original, v1); MSG_ReadDir(original, v2); // compute reflection vector // appPrintf("sp: (%g %g %g) -> (%g %g %g)\n",VECTOR_ARG(v1),VECTOR_ARG(v2));//!! CVec3 d; VectorSubtract(shotStart, shotEnd, d); d.NormalizeFast(); float back = dot(d, v2); for (int i = 0; i < 3; i++) v2[i] = d[i] - 2 * (d[i] - back * v2[i]); MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, cmd); MSG_WritePos(ext, v1); MSG_WriteDir(ext, v2); } return ext; case TE_SPLASH: { int count = MSG_ReadByte(original); MSG_ReadPos(original, v1); // pos int tmp = MSG_ReadByte(original); // dir int type = MSG_ReadByte(original); if (type != SPLASH_BLUE_WATER && type != SPLASH_BROWN_WATER) return original; // not bullet effect // find splash origin in static map splashes to avoid bullethit sounds for waterfalls etc. for (const originInfo_t *spl = bspfile.splashes; spl; spl = spl->next) { if (fabs(spl->origin[0] - v1[0]) < 1 && fabs(spl->origin[1] - v1[1]) < 1 && fabs(spl->origin[2] - v1[2]) < 1) // dir is quantized, so - make inprecisious compare return original; } //?? can add ripple effect on water, water smoke MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, TE_SPLASH); MSG_WriteByte(ext, count); MSG_WritePos(ext, v1); MSG_WriteByte(ext, tmp); MSG_WriteByte(ext, type - SPLASH_BLUE_WATER + SPLASH_BULLET_BLUE_WATER); } return ext; } return original; unguard; }