/* ================== CL_ParseParticles ================== */ void CL_ParseParticles( sizebuf_t *msg ) { vec3_t org, dir; int i, count, color; float life; BF_ReadVec3Coord( msg, org ); for( i = 0; i < 3; i++ ) dir[i] = BF_ReadChar( msg ) * (1.0f / 16); count = BF_ReadByte( msg ); color = BF_ReadByte( msg ); if( count == 255 ) count = 1024; life = BF_ReadByte( msg ) * 0.125f; if( life != 0.0f && count == 1 ) { particle_t *p; p = CL_AllocParticle( NULL ); if( !p ) return; p->die += life; p->color = color; p->type = pt_static; VectorCopy( org, p->org ); VectorCopy( dir, p->vel ); } else CL_RunParticleEffect( org, dir, color, count ); }
/* ================= CL_ParseTEnt ================= */ void CL_ParseTEnt (void) { int type; vec3_t pos; cdlight_t *dl; int rnd; explosion_t *ex; int cnt; type = MSG_ReadByte (); switch (type) { case TE_WIZSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 20, 30); S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, ATTN_NORM); { dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 250; dl->die = cl.time + 0.5; dl->decay = 300; R_ColorWizLight (dl); } break; case TE_KNIGHTSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 226, 20); S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, ATTN_NORM); { dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 250; dl->die = cl.time + 0.5; dl->decay = 300; R_ColorDLight (dl, 408, 242, 117); } break; case TE_SPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 0, 10); if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, ATTN_NORM); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, ATTN_NORM); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, ATTN_NORM); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, ATTN_NORM); } break; case TE_SUPERSPIKE: // super spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 0, 20); if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, ATTN_NORM); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, ATTN_NORM); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, ATTN_NORM); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, ATTN_NORM); } break; case TE_EXPLOSION: // rocket explosion particles pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (cl_explosion.value == 6) CL_TeleportSplash (pos); else if (cl_explosion.value == 7) CL_RunParticleEffect (pos, vec3_origin, 73, 20*32); else if (cl_explosion.value == 8) CL_RunParticleEffect (pos, vec3_origin, 225, 50); else if (cl_explosion.value != 1 && cl_explosion.value != 3) CL_ParticleExplosion (pos); dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; R_ColorDLight (dl, 408, 242, 117); // sound S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, ATTN_NORM); // sprite if (cl_explosion.value != 6 && cl_explosion.value != 7 && cl_explosion.value != 8) { if (!cl_explo_mod) cl_explo_mod = Mod_ForName ("progs/s_explod.spr", true); ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); ex->start = cl.time; ex->model = cl_explo_mod; } break; case TE_TAREXPLOSION: // tarbaby explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_BlobExplosion (pos); { dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; R_ColorDLight (dl, 399, 141, 228); } S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, ATTN_NORM); break; case TE_LIGHTNING1: // lightning bolts CL_ParseBeam (1); break; case TE_LIGHTNING2: // lightning bolts CL_ParseBeam (2); break; case TE_LIGHTNING3: // lightning bolts CL_ParseBeam (3); break; case TE_LAVASPLASH: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_LavaSplash (pos); break; case TE_TELEPORT: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_TeleportSplash (pos); break; case TE_GUNSHOT: // bullet hitting wall if (cls.nqprotocol) cnt = 1; else cnt = MSG_ReadByte (); pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 0, 20*cnt); break; case TE_BLOOD: // bullets hitting body if (cls.nqprotocol) { // NQ_TE_EXPLOSION2 int colorStart, colorLength; pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); colorStart = MSG_ReadByte (); colorLength = MSG_ReadByte (); CL_ParticleExplosion2 (pos, colorStart, colorLength); dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, ATTN_NORM); break; } cnt = MSG_ReadByte (); pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 73, 20*cnt); break; case TE_LIGHTNINGBLOOD: // lightning hitting body if (cls.nqprotocol) { // NQ_TE_BEAM - grappling hook beam CL_ParseBeam (4); break; } pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); CL_RunParticleEffect (pos, vec3_origin, 225, 50); break; default: Host_Error ("CL_ParseTEnt: bad type"); } }