/* ================= CL_ParseTEnt ================= */ void CL_ParseTEnt (void) { int type; vec3_t pos; #ifdef QUAKE2 vec3_t endpos; #endif dlight_t *dl; int rnd; int colorStart, colorLength; type = MSG_ReadByte (); switch (type) { case TE_WIZSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (r_part_spikes.value == 2 && !cl_q3gunshot_mod) cl_q3gunshot_mod = Mod_ForName ("progs/bullet.md3", true); R_RunParticleEffect (pos, vec3_origin, 20, 30); S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); break; case TE_KNIGHTSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (r_part_spikes.value == 2 && !cl_q3gunshot_mod) cl_q3gunshot_mod = Mod_ForName ("progs/bullet.md3", true); R_RunParticleEffect (pos, vec3_origin, 226, 20); S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); break; case TE_SPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (r_part_spikes.value == 2 && !cl_q3gunshot_mod) cl_q3gunshot_mod = Mod_ForName ("progs/bullet.md3", true); //R00k--start if (r_decal_bullets.value) { R_SpawnDecalStatic(pos, decal_mark, 8); } //R00k--end #ifdef GLTEST Test_Spawn (pos); #else R_RunParticleEffect (pos, vec3_origin, 0, 10); #endif if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); } break; case TE_SUPERSPIKE: // super spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (r_part_spikes.value == 2 && !cl_q3gunshot_mod) cl_q3gunshot_mod = Mod_ForName ("progs/bullet.md3", true); R_RunParticleEffect (pos, vec3_origin, 0, 20); //R00k--start if (r_decal_bullets.value) { R_SpawnDecalStatic(pos, decal_mark, 10); } //R00k--end if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); } break; case TE_GUNSHOT: // bullet hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_SurfacePoint(); if (r_part_gunshots.value == 2 && !cl_q3gunshot_mod) cl_q3gunshot_mod = Mod_ForName ("progs/bullet.md3", true); if(!Q_strncmp(texturehit,"sky",3) ) //Don't draw decals or sparks on the skybox break; //R00k--start if (r_decal_bullets.value) { R_SpawnDecalStatic(pos, decal_mark, 8); } //R00k--end if(!Q_strncmp(texturehit,"metal",5) ) { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_mric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_mric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_mric3, pos, 1, 1); } else if(!Q_strncmp(texturehit,"wood",4) ) { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_wric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_wric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_wric3, pos, 1, 1); } else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); } R_RunParticleEffect (pos, vec3_origin, 0, 20); break; case TE_EXPLOSION: // rocket explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_ParticleExplosion (pos); if (r_decal_explosions.value) { R_SpawnDecalStatic(pos, decal_burn, 100); } 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, 1); break; case TE_TAREXPLOSION: // tarbaby explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_BlobExplosion (pos); S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; case TE_LIGHTNING1: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); break; case TE_LIGHTNING2: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true)); break; case TE_LIGHTNING3: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true)); break; // PGM 01/21/97 case TE_BEAM: // grappling hook beam CL_ParseBeam (Mod_ForName("progs/beam.mdl", true)); break; // PGM 01/21/97 case TE_LAVASPLASH: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_LavaSplash (pos); dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 150; dl->die = cl.time + 0.75; dl->decay = 200; break; case TE_TELEPORT: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); if (r_part_telesplash.value == 2 && !cl_q3teleport_mod) cl_q3teleport_mod = Mod_ForName ("progs/telep.md3", true); R_TeleportSplash (pos); break; case TE_EXPLOSION2: // color mapped explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); colorStart = MSG_ReadByte (); colorLength = MSG_ReadByte (); R_ParticleExplosion2 (pos, colorStart, colorLength); if (r_decal_explosions.value) { R_SpawnDecalStatic(pos, decal_burn, 100); } 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, 1); break; #ifdef QUAKE2 case TE_IMPLOSION: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); break; case TE_RAILTRAIL: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); endpos[0] = MSG_ReadCoord (); endpos[1] = MSG_ReadCoord (); endpos[2] = MSG_ReadCoord (); S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); R_RocketTrail (pos, endpos, 0+128); R_ParticleExplosion (endpos); dl = CL_AllocDlight (-1); VectorCopy (endpos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; break; #endif default: Sys_Error ("CL_ParseTEnt: bad type"); } }
/* ================= CL_ParseTEnt ================= */ void CL_ParseTEnt (void) { int type; vec3_t pos; #ifdef QUAKE2 vec3_t endpos; #endif dlight_t *dl; int rnd; int colorStart, colorLength; type = MSG_ReadByte (); switch (type) { case TE_WIZSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_RunParticleEffect (pos, vec3_origin, 20, 30); S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); break; case TE_KNIGHTSPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_RunParticleEffect (pos, vec3_origin, 226, 20); S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); break; case TE_SPIKE: // spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); #ifdef GLTEST Test_Spawn (pos); #else R_RunParticleEffect (pos, vec3_origin, 0, 10); #endif if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); } break; case TE_SUPERSPIKE: // super spike hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_RunParticleEffect (pos, vec3_origin, 0, 20); if ( rand() % 5 ) S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); else { rnd = rand() & 3; if (rnd == 1) S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); else if (rnd == 2) S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); else S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); } break; case TE_GUNSHOT: // bullet hitting wall pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_RunParticleEffect (pos, vec3_origin, 0, 20); break; case TE_EXPLOSION: // rocket explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_ParticleExplosion (pos); dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5f; dl->decay = 300; S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; case TE_TAREXPLOSION: // tarbaby explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_BlobExplosion (pos); S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; case TE_LIGHTNING1: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt.mdl", TRUE)); break; case TE_LIGHTNING2: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", TRUE)); break; case TE_LIGHTNING3: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", TRUE)); break; // PGM 01/21/97 case TE_BEAM: // grappling hook beam CL_ParseBeam (Mod_ForName("progs/beam.mdl", TRUE)); break; // PGM 01/21/97 case TE_LAVASPLASH: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_LavaSplash (pos); break; case TE_TELEPORT: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); R_TeleportSplash (pos); break; case TE_EXPLOSION2: // color mapped explosion pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); colorStart = MSG_ReadByte (); colorLength = MSG_ReadByte (); R_ParticleExplosion2 (pos, colorStart, colorLength); dl = CL_AllocDlight (0); VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5f; dl->decay = 300; S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; #ifdef QUAKE2 case TE_IMPLOSION: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); break; case TE_RAILTRAIL: pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); endpos[0] = MSG_ReadCoord (); endpos[1] = MSG_ReadCoord (); endpos[2] = MSG_ReadCoord (); S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); R_RocketTrail (pos, endpos, 0+128); R_ParticleExplosion (endpos); dl = CL_AllocDlight (-1); VectorCopy (endpos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5f; dl->decay = 300; break; #endif default: Sys_Error ("CL_ParseTEnt: bad type"); } }
/* =============== CL_RelinkEntities =============== */ void CL_RelinkEntities(void) { entity_t *ent; int i, j; float frac, f, d; vec3_t delta; float bobjrotate; vec3_t oldorg; dlight_t *dl; // determine partial update time frac = CL_LerpPoint(); cl_numvisedicts = 0; // // interpolate player info // for (i = 0; i < 3; i++) cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); if (cls.demoplayback) { // interpolate the angles for (j = 0; j < 3; j++) { d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; if (d > 180) d -= 360; else if (d < -180) d += 360; cl.viewangles[j] = cl.mviewangles[1][j] + frac * d; } } bobjrotate = anglemod(100 * cl.time); // start on the entity after the world for (i = 1, ent = cl_entities + 1; i < cl.num_entities; i++, ent++) { if (!ent->model) { // empty slot if (ent->forcelink) R_RemoveEfrags(ent); // just became empty continue; } // if the object wasn't included in the last packet, remove it if (ent->msgtime != cl.mtime[0]) { ent->model = NULL; continue; } VectorCopy(ent->origin, oldorg); if (ent->forcelink) { // the entity was not updated in the last message // so move to the final spot VectorCopy(ent->msg_origins[0], ent->origin); VectorCopy(ent->msg_angles[0], ent->angles); } else { // if the delta is large, assume a teleport and don't lerp f = frac; for (j = 0; j < 3; j++) { delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; if (delta[j] > 100 || delta[j] < -100) f = 1; // assume a teleportation, not a motion } // interpolate the origin and angles for (j = 0; j < 3; j++) { ent->origin[j] = ent->msg_origins[1][j] + f * delta[j]; d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; if (d > 180) d -= 360; else if (d < -180) d += 360; ent->angles[j] = ent->msg_angles[1][j] + f * d; } } // rotate binary objects locally if (ent->model->flags & EF_ROTATE) ent->angles[1] = bobjrotate; /* * FIXME - Some of these entity effects may be mutually exclusive? * work out which bits can be done better (e.g. I've already done the * RED|BLUE bit a little better...) */ if (ent->effects & EF_BRIGHTFIELD) R_EntityParticles(ent); if (ent->effects & EF_MUZZLEFLASH) { vec3_t fv, rv, uv; dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->origin[2] += 16; AngleVectors(ent->angles, fv, rv, uv); VectorMA(dl->origin, 18, fv, dl->origin); dl->radius = 200 + (rand() & 31); dl->minlight = 32; dl->die = cl.time + 0.1; dl->color = dl_colors[DLIGHT_FLASH]; } if (ent->effects & EF_BRIGHTLIGHT) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->origin[2] += 16; dl->radius = 400 + (rand() & 31); dl->die = cl.time + 0.001; dl->color = dl_colors[DLIGHT_FLASH]; } if (ent->effects & EF_DIMLIGHT) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200 + (rand() & 31); dl->die = cl.time + 0.001; dl->color = dl_colors[DLIGHT_FLASH]; } if ((ent->effects & (EF_RED | EF_BLUE)) == (EF_RED | EF_BLUE)) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200 + (rand() & 31); dl->die = cl.time + 0.001; dl->color = dl_colors[DLIGHT_PURPLE]; } else if (ent->effects & EF_BLUE) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200 + (rand() & 31); dl->die = cl.time + 0.001; dl->color = dl_colors[DLIGHT_BLUE]; } else if (ent->effects & EF_RED) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200 + (rand() & 31); dl->die = cl.time + 0.001; dl->color = dl_colors[DLIGHT_RED]; } if (ent->model->flags & EF_GIB) R_RocketTrail(oldorg, ent->origin, 2); else if (ent->model->flags & EF_ZOMGIB) R_RocketTrail(oldorg, ent->origin, 4); else if (ent->model->flags & EF_TRACER) R_RocketTrail(oldorg, ent->origin, 3); else if (ent->model->flags & EF_TRACER2) R_RocketTrail(oldorg, ent->origin, 5); else if (ent->model->flags & EF_ROCKET) { R_RocketTrail(oldorg, ent->origin, 0); dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200; dl->die = cl.time + 0.01; } else if (ent->model->flags & EF_GRENADE) R_RocketTrail(oldorg, ent->origin, 1); else if (ent->model->flags & EF_TRACER3) R_RocketTrail(oldorg, ent->origin, 6); ent->forcelink = false; if (i == cl.viewentity && !chase_active.value) continue; if (cl_numvisedicts < MAX_VISEDICTS) { cl_visedicts[cl_numvisedicts] = ent; cl_numvisedicts++; } } }
void CL_RelinkEntities(void) { entity_t *ent; int i, j; float frac, f, d; vec3_t delta; float bobjrotate; vec3_t oldorg; dlight_t *dl; // determine partial update time frac = CL_LerpPoint(); cl_numvisedicts = 0; // interpolate player info for (i = 0; i < 3; i++) cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); if (cls.demoplayback) { // interpolate the angles for (j = 0; j < 3; j++) { d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; if (d > 180) d -= 360; else if (d < -180) d += 360; cl.viewangles[j] = cl.mviewangles[1][j] + frac*d; } } bobjrotate = anglemod(100 * cl.time); // start on the entity after the world for (i = 1, ent = cl_entities + 1; i < cl.num_entities; i++, ent++) { if (!ent->model) { // empty slot if (ent->forcelink) R_RemoveEfrags(ent); // just became empty continue; } // if the object wasn't included in the last packet, remove it if (ent->msgtime != cl.mtime[0]) { ent->model = NULL; //qmb :interpolation // [email protected]: model transform interpolation ent->frame_start_time = 0; ent->translate_start_time = 0; ent->rotate_start_time = 0; //qmb :end continue; } VectorCopy(ent->origin, oldorg); if (ent->forcelink) { // the entity was not updated in the last message // so move to the final spot VectorCopy(ent->msg_origins[0], ent->origin); VectorCopy(ent->msg_angles[0], ent->angles); } else { // if the delta is large, assume a teleport and don't lerp f = frac; for (j = 0; j < 3; j++) { delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; if (delta[j] > 100 || delta[j] < -100) f = 1; // assume a teleportation, not a motion if (f >= 1) { ent->frame_start_time = 0; ent->translate_start_time = 0; ent->rotate_start_time = 0; } } // interpolate the origin and angles for (j = 0; j < 3; j++) { ent->origin[j] = ent->msg_origins[1][j] + f * delta[j]; d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; if (d > 180) d -= 360; else if (d < -180) d += 360; ent->angles[j] = ent->msg_angles[1][j] + f*d; } } // rotate binary objects locally if (ent->model->flags & EF_ROTATE) { ent->angles[1] = bobjrotate; // MUFF - makes them bob as well as rotate ;) ent->origin[2] += ((sin(bobjrotate / 90 * M_PI) * 5) + 5); } if (ent->effects & EF_BRIGHTFIELD) R_EntityParticles(ent); if (ent->effects & EF_MUZZLEFLASH) { vec3_t fv, rv, uv; dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->origin[2] += 16; AngleVectors(ent->angles, fv, rv, uv); VectorMA(dl->origin, 18, fv, dl->origin); dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time + 0.1; dl->colour[0] = 0.6f; dl->colour[1] = 0.4f; dl->colour[2] = 0.2f; //qmb :coloured lighting } if (ent->effects & EF_BRIGHTLIGHT) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->origin[2] += 16; dl->radius = 400 + (rand()&31); dl->die = cl.time + 0.001; } if (ent->effects & EF_DIMLIGHT) { dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200 + (rand()&31); dl->die = cl.time + 0.001; } if (ent->model->flags & EF_GIB) R_RocketTrail(oldorg, ent->origin, 2); else if (ent->model->flags & EF_ZOMGIB) R_RocketTrail(oldorg, ent->origin, 4); else if (ent->model->flags & EF_TRACER) R_RocketTrail(oldorg, ent->origin, 3); else if (ent->model->flags & EF_TRACER2) R_RocketTrail(oldorg, ent->origin, 5); else if (ent->model->flags & EF_ROCKET) { R_RocketTrail(oldorg, ent->origin, 0); dl = CL_AllocDlight(i); VectorCopy(ent->origin, dl->origin); dl->radius = 200; dl->die = cl.time + 0.01; dl->colour[0] = 0.6f; dl->colour[1] = 0.4f; dl->colour[2] = 0.4f; //qmb :coloured lighting } else if (ent->model->flags & EF_GRENADE) R_RocketTrail(oldorg, ent->origin, 1); else if (ent->model->flags & EF_TRACER3) R_RocketTrail(oldorg, ent->origin, 6); ent->forcelink = false; if (i == cl.viewentity) continue; if (cl_numvisedicts < MAX_VISEDICTS) { cl_visedicts[cl_numvisedicts] = ent; cl_numvisedicts++; } } }
/* =============== CL_LinkPacketEntities =============== */ void CL_LinkPacketEntities (void) { entity_t *ent; packet_entities_t *pack; entity_state_t *s1, *s2; float f; model_t *model; vec3_t old_origin; float autorotate; int i; int pnum; dlight_t *dl; pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; autorotate = anglemod(100*cl.time); f = 0; // FIXME: no interpolation right now for (pnum=0 ; pnum<pack->num_entities ; pnum++) { s1 = &pack->entities[pnum]; s2 = s1; // FIXME: no interpolation right now // spawn light flashes, even ones coming from invisible objects if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3); else if (s1->effects & EF_BLUE) CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1); else if (s1->effects & EF_RED) CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2); else if (s1->effects & EF_BRIGHTLIGHT) CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0); else if (s1->effects & EF_DIMLIGHT) CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0); // if set to invisible, skip if (!s1->modelindex) continue; // create a new entity if (cl_numvisedicts == MAX_VISEDICTS) break; // object list is full ent = &cl_visedicts[cl_numvisedicts]; cl_numvisedicts++; ent->keynum = s1->number; ent->model = model = cl.model_precache[s1->modelindex]; // set colormap if (s1->colormap && (s1->colormap < MAX_CLIENTS) && !strcmp(ent->model->name,"progs/player.mdl") ) { ent->colormap = cl.players[s1->colormap-1].translations; ent->scoreboard = &cl.players[s1->colormap-1]; } else { ent->colormap = vid.colormap; ent->scoreboard = NULL; } // set skin ent->skinnum = s1->skinnum; // set frame ent->frame = s1->frame; // rotate binary objects locally if (model->flags & EF_ROTATE) { ent->angles[0] = 0; ent->angles[1] = autorotate; ent->angles[2] = 0; } else { float a1, a2; for (i=0 ; i<3 ; i++) { a1 = s1->angles[i]; a2 = s2->angles[i]; if (a1 - a2 > 180) a1 -= 360; if (a1 - a2 < -180) a1 += 360; ent->angles[i] = a2 + f * (a1 - a2); } } // calculate origin for (i=0 ; i<3 ; i++) ent->origin[i] = s2->origin[i] + f * (s1->origin[i] - s2->origin[i]); // add automatic particle trails if (!model->flags) continue; // scan the old entity display list for a matching for (i=0 ; i<cl_oldnumvisedicts ; i++) { if (cl_oldvisedicts[i].keynum == ent->keynum) { VectorCopy (cl_oldvisedicts[i].origin, old_origin); break; } } if (i == cl_oldnumvisedicts) continue; // not in last message for (i=0 ; i<3 ; i++) if ( abs(old_origin[i] - ent->origin[i]) > 128) { // no trail if too far VectorCopy (ent->origin, old_origin); break; } if (model->flags & EF_ROCKET) { R_RocketTrail (old_origin, ent->origin, 0); dl = CL_AllocDlight (s1->number); VectorCopy (ent->origin, dl->origin); dl->radius = 200; dl->die = cl.time + 0.1; } else if (model->flags & EF_GRENADE) R_RocketTrail (old_origin, ent->origin, 1); else if (model->flags & EF_GIB) R_RocketTrail (old_origin, ent->origin, 2); else if (model->flags & EF_ZOMGIB) R_RocketTrail (old_origin, ent->origin, 4); else if (model->flags & EF_TRACER) R_RocketTrail (old_origin, ent->origin, 3); else if (model->flags & EF_TRACER2) R_RocketTrail (old_origin, ent->origin, 5); else if (model->flags & EF_TRACER3) R_RocketTrail (old_origin, ent->origin, 6); } }