/// <summary> /// R_BlobExplosion /// </summary> public static void BlobExplosion(ref Vector3 org) { for (int i = 0; i < 1024; i++) { particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)(Client.cl.time + 1 + (Sys.Random() & 8) * 0.05); if ((i & 1) != 0) { p.type = ptype_t.pt_blob; p.color = 66 + Sys.Random() % 6; } else { p.type = ptype_t.pt_blob2; p.color = 150 + Sys.Random() % 6; } p.org = org + new Vector3((Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16); p.vel = new Vector3((Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256); } }
/// <summary> /// R_LavaSplash /// </summary> public static void LavaSplash(ref Vector3 org) { Vector3 dir; for (int i = -16; i < 16; i++) { for (int j = -16; j < 16; j++) { for (int k = 0; k < 1; k++) { particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)(Client.cl.time + 2 + (Sys.Random() & 31) * 0.02); p.color = 224 + (Sys.Random() & 7); p.type = ptype_t.pt_slowgrav; dir.X = j * 8 + (Sys.Random() & 7); dir.Y = i * 8 + (Sys.Random() & 7); dir.Z = 256; p.org = org + dir; p.org.Z += Sys.Random() & 63; Mathlib.Normalize(ref dir); float vel = 50 + (Sys.Random() & 63); p.vel = dir * vel; } } } }
/// <summary> /// R_TeleportSplash /// </summary> public static void TeleportSplash(ref Vector3 org) { for (int i = -16; i < 16; i += 4) { for (int j = -16; j < 16; j += 4) { for (int k = -24; k < 32; k += 4) { particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)(Client.cl.time + 0.2 + (Sys.Random() & 7) * 0.02); p.color = 7 + (Sys.Random() & 7); p.type = ptype_t.pt_slowgrav; Vector3 dir = new Vector3(j * 8, i * 8, k * 8); p.org = org + new Vector3(i + (Sys.Random() & 3), j + (Sys.Random() & 3), k + (Sys.Random() & 3)); Mathlib.Normalize(ref dir); float vel = 50 + (Sys.Random() & 63); p.vel = dir * vel; } } } }
/// <summary> /// R_ParticleExplosion /// </summary> public static void ParticleExplosion(ref Vector3 org) { for (int i = 0; i < 1024; i++) // Uze: Why 1024 if MAX_PARTICLES = 2048? { particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)Client.cl.time + 5; p.color = _Ramp1[0]; p.ramp = Sys.Random() & 3; if ((i & 1) != 0) { p.type = ptype_t.pt_explode; } else { p.type = ptype_t.pt_explode2; } p.org = org + new Vector3((Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16); p.vel = new Vector3((Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256); } }
/// <summary> /// R_ParticleExplosion2 /// </summary> public static void ParticleExplosion(ref Vector3 org, int colorStart, int colorLength) { int colorMod = 0; for (int i = 0; i < 512; i++) { particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)(Client.cl.time + 0.3); p.color = colorStart + (colorMod % colorLength); colorMod++; p.type = ptype_t.pt_blob; p.org = org + new Vector3((Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16); p.vel = new Vector3((Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256); } }
/// <summary> /// R_EntityParticles /// </summary> public static void EntityParticles(entity_t ent) { float dist = 64; if (_AVelocities[0].X == 0) { for (int i = 0; i < NUMVERTEXNORMALS; i++) { _AVelocities[i].X = (Sys.Random() & 255) * 0.01f; _AVelocities[i].Y = (Sys.Random() & 255) * 0.01f; _AVelocities[i].Z = (Sys.Random() & 255) * 0.01f; } } for (int i = 0; i < NUMVERTEXNORMALS; i++) { double angle = Client.cl.time * _AVelocities[i].X; double sy = Math.Sin(angle); double cy = Math.Cos(angle); angle = Client.cl.time * _AVelocities[i].Y; double sp = Math.Sin(angle); double cp = Math.Cos(angle); angle = Client.cl.time * _AVelocities[i].Z; double sr = Math.Sin(angle); double cr = Math.Cos(angle); Vector3 forward = new Vector3((float)(cp * cy), (float)(cp * sy), (float)-sp); particle_t p = AllocParticle(); if (p == null) { return; } p.die = (float)(Client.cl.time + 0.01); p.color = 0x6f; p.type = ptype_t.pt_explode; p.org = ent.origin + Anorms.Values[i] * dist + forward * _BeamLength; } }
/// <summary> /// SV_MoveToGoal /// </summary> public static void MoveToGoal() { edict_t ent = ProgToEdict(Progs.GlobalStruct.self); edict_t goal = ProgToEdict(ent.v.goalentity); float dist = QBuiltins.GetFloat(OFS.OFS_PARM0); if (((int)ent.v.flags & (EdictFlags.FL_ONGROUND | EdictFlags.FL_FLY | EdictFlags.FL_SWIM)) == 0) { QBuiltins.ReturnFloat(0); return; } // if the next step hits the enemy, return immediately if (ProgToEdict(ent.v.enemy) != sv.edicts[0] && CloseEnough(ent, goal, dist)) { return; } // bump around... if ((Sys.Random() & 3) == 1 || !StepDirection(ent, ent.v.ideal_yaw, dist)) { NewChaseDir(ent, goal, dist); } }
/// <summary> /// R_RunParticleEffect /// </summary> public static void RunParticleEffect(ref Vector3 org, ref Vector3 dir, int color, int count) { for (int i = 0; i < count; i++) { particle_t p = AllocParticle(); if (p == null) { return; } if (count == 1024) { // rocket explosion p.die = (float)Client.cl.time + 5; p.color = _Ramp1[0]; p.ramp = Sys.Random() & 3; if ((i & 1) != 0) { p.type = ptype_t.pt_explode; } else { p.type = ptype_t.pt_explode2; } p.org = org + new Vector3((Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16, (Sys.Random() % 32) - 16); p.vel = new Vector3((Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256, (Sys.Random() % 512) - 256); } else { p.die = (float)Client.cl.time + 0.1f * (Sys.Random() % 5); p.color = (color & ~7) + (Sys.Random() & 7); p.type = ptype_t.pt_slowgrav; p.org = org + new Vector3((Sys.Random() & 15) - 8, (Sys.Random() & 15) - 8, (Sys.Random() & 15) - 8); p.vel = dir * 15.0f; } } }
/* * ================= * PF_Random * * Returns a number from 0<= num < 1 * * random() * ================= */ static void PF_random() { float num = (Sys.Random() & 0x7fff) / ((float)0x7fff); ReturnFloat(num); }
/// <summary> /// SV_NewChaseDir /// </summary> static void NewChaseDir(edict_t actor, edict_t enemy, float dist) { float olddir = Mathlib.AngleMod((int)(actor.v.ideal_yaw / 45) * 45); float turnaround = Mathlib.AngleMod(olddir - 180); float deltax = enemy.v.origin.x - actor.v.origin.x; float deltay = enemy.v.origin.y - actor.v.origin.y; v3f d; if (deltax > 10) { d.y = 0; } else if (deltax < -10) { d.y = 180; } else { d.y = DI_NODIR; } if (deltay < -10) { d.z = 270; } else if (deltay > 10) { d.z = 90; } else { d.z = DI_NODIR; } // try direct route float tdir; if (d.y != DI_NODIR && d.z != DI_NODIR) { if (d.y == 0) { tdir = (d.z == 90 ? 45 : 315); } else { tdir = (d.z == 90 ? 135 : 215); } if (tdir != turnaround && StepDirection(actor, tdir, dist)) { return; } } // try other directions if (((Sys.Random() & 3) & 1) != 0 || Math.Abs(deltay) > Math.Abs(deltax)) { tdir = d.y; d.y = d.z; d.z = tdir; } if (d.y != DI_NODIR && d.y != turnaround && StepDirection(actor, d.y, dist)) { return; } if (d.z != DI_NODIR && d.z != turnaround && StepDirection(actor, d.z, dist)) { return; } // there is no direct path to the player, so pick another direction if (olddir != DI_NODIR && StepDirection(actor, olddir, dist)) { return; } if ((Sys.Random() & 1) != 0) //randomly determine direction of search { for (tdir = 0; tdir <= 315; tdir += 45) { if (tdir != turnaround && StepDirection(actor, tdir, dist)) { return; } } } else { for (tdir = 315; tdir >= 0; tdir -= 45) { if (tdir != turnaround && StepDirection(actor, tdir, dist)) { return; } } } if (turnaround != DI_NODIR && StepDirection(actor, turnaround, dist)) { return; } actor.v.ideal_yaw = olddir; // can't move // if a bridge was pulled out from underneath a monster, it may not have // a valid standing position at all if (!CheckBottom(actor)) { FixCheckBottom(actor); } }
// CL_UpdateTEnts static void UpdateTempEntities() { _NumTempEntities = 0; // update lightning for (int i = 0; i < MAX_BEAMS; i++) { beam_t b = _Beams[i]; if (b.model == null || b.endtime < cl.time) { continue; } // if coming from the player, update the start position if (b.entity == cl.viewentity) { b.start = _Entities[cl.viewentity].origin; } // calculate pitch and yaw Vector3 dist = b.end - b.start; float yaw, pitch, forward; if (dist.Y == 0 && dist.X == 0) { yaw = 0; if (dist.Z > 0) { pitch = 90; } else { pitch = 270; } } else { yaw = (int)(Math.Atan2(dist.Y, dist.X) * 180 / Math.PI); if (yaw < 0) { yaw += 360; } forward = (float)Math.Sqrt(dist.X * dist.X + dist.Y * dist.Y); pitch = (int)(Math.Atan2(dist.Z, forward) * 180 / Math.PI); if (pitch < 0) { pitch += 360; } } // add new entities for the lightning Vector3 org = b.start; float d = Mathlib.Normalize(ref dist); while (d > 0) { entity_t ent = NewTempEntity(); if (ent == null) { return; } ent.origin = org; ent.model = b.model; ent.angles.X = pitch; ent.angles.Y = yaw; ent.angles.Z = Sys.Random() % 360; org += dist * 30; // Uze: is this code bug (i is outer loop variable!!!) or what?????????????? //for (i=0 ; i<3 ; i++) // org[i] += dist[i]*30; d -= 30; } } }
/// <summary> /// CL_ParseTEnt /// </summary> static void ParseTempEntity() { Vector3 pos; dlight_t dl; int type = Net.Reader.ReadByte(); switch (type) { case Protocol.TE_WIZSPIKE: // spike hitting wall pos = Net.Reader.ReadCoords(); Render.RunParticleEffect(ref pos, ref Common.ZeroVector, 20, 30); Sound.StartSound(-1, 0, _SfxWizHit, ref pos, 1, 1); break; case Protocol.TE_KNIGHTSPIKE: // spike hitting wall pos = Net.Reader.ReadCoords(); Render.RunParticleEffect(ref pos, ref Common.ZeroVector, 226, 20); Sound.StartSound(-1, 0, _SfxKnigtHit, ref pos, 1, 1); break; case Protocol.TE_SPIKE: // spike hitting wall pos = Net.Reader.ReadCoords(); #if GLTEST Test_Spawn(pos); #else Render.RunParticleEffect(ref pos, ref Common.ZeroVector, 0, 10); #endif if ((Sys.Random() % 5) != 0) { Sound.StartSound(-1, 0, _SfxTink1, ref pos, 1, 1); } else { int rnd = Sys.Random() & 3; if (rnd == 1) { Sound.StartSound(-1, 0, _SfxRic1, ref pos, 1, 1); } else if (rnd == 2) { Sound.StartSound(-1, 0, _SfxRic2, ref pos, 1, 1); } else { Sound.StartSound(-1, 0, _SfxRic3, ref pos, 1, 1); } } break; case Protocol.TE_SUPERSPIKE: // super spike hitting wall pos = Net.Reader.ReadCoords(); Render.RunParticleEffect(ref pos, ref Common.ZeroVector, 0, 20); if ((Sys.Random() % 5) != 0) { Sound.StartSound(-1, 0, _SfxTink1, ref pos, 1, 1); } else { int rnd = Sys.Random() & 3; if (rnd == 1) { Sound.StartSound(-1, 0, _SfxRic1, ref pos, 1, 1); } else if (rnd == 2) { Sound.StartSound(-1, 0, _SfxRic2, ref pos, 1, 1); } else { Sound.StartSound(-1, 0, _SfxRic3, ref pos, 1, 1); } } break; case Protocol.TE_GUNSHOT: // bullet hitting wall pos = Net.Reader.ReadCoords(); Render.RunParticleEffect(ref pos, ref Common.ZeroVector, 0, 20); break; case Protocol.TE_EXPLOSION: // rocket explosion pos = Net.Reader.ReadCoords(); Render.ParticleExplosion(ref pos); dl = AllocDlight(0); dl.origin = pos; dl.radius = 350; dl.die = (float)Client.cl.time + 0.5f; dl.decay = 300; Sound.StartSound(-1, 0, _SfxRExp3, ref pos, 1, 1); break; case Protocol.TE_TAREXPLOSION: // tarbaby explosion pos = Net.Reader.ReadCoords(); Render.BlobExplosion(ref pos); Sound.StartSound(-1, 0, _SfxRExp3, ref pos, 1, 1); break; case Protocol.TE_LIGHTNING1: // lightning bolts ParseBeam(Mod.ForName("progs/bolt.mdl", true)); break; case Protocol.TE_LIGHTNING2: // lightning bolts ParseBeam(Mod.ForName("progs/bolt2.mdl", true)); break; case Protocol.TE_LIGHTNING3: // lightning bolts ParseBeam(Mod.ForName("progs/bolt3.mdl", true)); break; // PGM 01/21/97 case Protocol.TE_BEAM: // grappling hook beam ParseBeam(Mod.ForName("progs/beam.mdl", true)); break; // PGM 01/21/97 case Protocol.TE_LAVASPLASH: pos = Net.Reader.ReadCoords(); Render.LavaSplash(ref pos); break; case Protocol.TE_TELEPORT: pos = Net.Reader.ReadCoords(); Render.TeleportSplash(ref pos); break; case Protocol.TE_EXPLOSION2: // color mapped explosion pos = Net.Reader.ReadCoords(); int colorStart = Net.Reader.ReadByte(); int colorLength = Net.Reader.ReadByte(); Render.ParticleExplosion(ref pos, colorStart, colorLength); dl = AllocDlight(0); dl.origin = pos; dl.radius = 350; dl.die = (float)cl.time + 0.5f; dl.decay = 300; Sound.StartSound(-1, 0, _SfxRExp3, ref pos, 1, 1); break; default: Sys.Error("CL_ParseTEnt: bad type"); break; } }
// S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) public static void StartSound(int entnum, int entchannel, sfx_t sfx, ref Vector3 origin, float fvol, float attenuation) { if (!_SoundStarted || sfx == null) { return; } if (_NoSound.Value != 0) { return; } int vol = (int)(fvol * 255); // pick a channel to play on channel_t target_chan = PickChannel(entnum, entchannel); if (target_chan == null) { return; } // spatialize //memset (target_chan, 0, sizeof(*target_chan)); target_chan.origin = origin; target_chan.dist_mult = attenuation / _SoundNominalClipDist; target_chan.master_vol = vol; target_chan.entnum = entnum; target_chan.entchannel = entchannel; Spatialize(target_chan); if (target_chan.leftvol == 0 && target_chan.rightvol == 0) { return; // not audible at all } // new channel sfxcache_t sc = LoadSound(sfx); if (sc == null) { target_chan.sfx = null; return; // couldn't load the sound's data } target_chan.sfx = sfx; target_chan.pos = 0; target_chan.end = _PaintedTime + sc.length; // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder for (int i = Ambients.NUM_AMBIENTS; i < Ambients.NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS; i++) { channel_t check = _Channels[i]; if (check == target_chan) { continue; } if (check.sfx == sfx && check.pos == 0) { int skip = Sys.Random((int)(0.1 * _shm.speed));// rand() % (int)(0.1 * shm->speed); if (skip >= target_chan.end) { skip = target_chan.end - 1; } target_chan.pos += skip; target_chan.end -= skip; break; } } }
/// <summary> /// R_RocketTrail /// </summary> public static void RocketTrail(ref Vector3 start, ref Vector3 end, int type) { Vector3 vec = end - start; float len = Mathlib.Normalize(ref vec); int dec; if (type < 128) { dec = 3; } else { dec = 1; type -= 128; } while (len > 0) { len -= dec; particle_t p = AllocParticle(); if (p == null) { return; } p.vel = Vector3.Zero; p.die = (float)Client.cl.time + 2; switch (type) { case 0: // rocket trail p.ramp = (Sys.Random() & 3); p.color = _Ramp3[(int)p.ramp]; p.type = ptype_t.pt_fire; p.org = new Vector3(start.X + ((Sys.Random() % 6) - 3), start.Y + ((Sys.Random() % 6) - 3), start.Z + ((Sys.Random() % 6) - 3)); break; case 1: // smoke smoke p.ramp = (Sys.Random() & 3) + 2; p.color = _Ramp3[(int)p.ramp]; p.type = ptype_t.pt_fire; p.org = new Vector3(start.X + ((Sys.Random() % 6) - 3), start.Y + ((Sys.Random() % 6) - 3), start.Z + ((Sys.Random() % 6) - 3)); break; case 2: // blood p.type = ptype_t.pt_grav; p.color = 67 + (Sys.Random() & 3); p.org = new Vector3(start.X + ((Sys.Random() % 6) - 3), start.Y + ((Sys.Random() % 6) - 3), start.Z + ((Sys.Random() % 6) - 3)); break; case 3: case 5: // tracer p.die = (float)Client.cl.time + 0.5f; p.type = ptype_t.pt_static; if (type == 3) { p.color = 52 + ((_TracerCount & 4) << 1); } else { p.color = 230 + ((_TracerCount & 4) << 1); } _TracerCount++; p.org = start; if ((_TracerCount & 1) != 0) { p.vel.X = 30 * vec.Y; // Uze: why??? p.vel.Y = 30 * -vec.X; } else { p.vel.X = 30 * -vec.Y; p.vel.Y = 30 * vec.X; } break; case 4: // slight blood p.type = ptype_t.pt_grav; p.color = 67 + (Sys.Random() & 3); p.org = new Vector3(start.X + ((Sys.Random() % 6) - 3), start.Y + ((Sys.Random() % 6) - 3), start.Z + ((Sys.Random() % 6) - 3)); len -= 3; break; case 6: // voor trail p.color = 9 * 16 + 8 + (Sys.Random() & 3); p.type = ptype_t.pt_static; p.die = (float)Client.cl.time + 0.3f; p.org = new Vector3(start.X + ((Sys.Random() % 15) - 8), start.Y + ((Sys.Random() % 15) - 8), start.Z + ((Sys.Random() % 15) - 8)); break; } start += vec; } }
/// <summary> /// CL_RelinkEntities /// </summary> static void RelinkEntities() { // determine partial update time float frac = LerpPoint(); NumVisEdicts = 0; // // interpolate player info // cl.velocity = cl.mvelocity[1] + frac * (cl.mvelocity[0] - cl.mvelocity[1]); if (cls.demoplayback) { // interpolate the angles Vector3 angleDelta = cl.mviewangles[0] - cl.mviewangles[1]; Mathlib.CorrectAngles180(ref angleDelta); cl.viewangles = cl.mviewangles[1] + frac * angleDelta; } float bobjrotate = Mathlib.AngleMod(100 * cl.time); // start on the entity after the world for (int i = 1; i < cl.num_entities; i++) { entity_t ent = _Entities[i]; if (ent.model == null) { // empty slot if (ent.forcelink) { Render.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; ent.FrameStartTime = 0; ent.TranslateStartTime = 0; ent.RotateStartTime = 0; continue; } Vector3 oldorg = ent.origin; if (ent.forcelink) { // the entity was not updated in the last message // so move to the final spot ent.origin = ent.msg_origins[0]; ent.angles = ent.msg_angles[0]; } else { // if the delta is large, assume a teleport and don't lerp float f = frac; Vector3 delta = ent.msg_origins[0] - ent.msg_origins[1]; if (Math.Abs(delta.X) > 100 || Math.Abs(delta.Y) > 100 || Math.Abs(delta.Z) > 100) { f = 1; // assume a teleportation, not a motion } // [email protected]: model transform interpolation // interpolation should be reset in the event of a large delta if (f >= 1) { ent.FrameStartTime = 0; ent.TranslateStartTime = 0; ent.RotateStartTime = 0; } // interpolate the origin and angles ent.origin = ent.msg_origins[1] + f * delta; Vector3 angleDelta = ent.msg_angles[0] - ent.msg_angles[1]; Mathlib.CorrectAngles180(ref angleDelta); ent.angles = ent.msg_angles[1] + f * angleDelta; } // rotate binary objects locally if ((ent.model.flags & EF.EF_ROTATE) != 0) { ent.angles.Y = bobjrotate; } if ((ent.effects & EntityEffects.EF_BRIGHTFIELD) != 0) { Render.EntityParticles(ent); } if ((ent.effects & EntityEffects.EF_MUZZLEFLASH) != 0) { dlight_t dl = AllocDlight(i); dl.origin = ent.origin; dl.origin.Z += 16; Vector3 fv, rv, uv; Mathlib.AngleVectors(ref ent.angles, out fv, out rv, out uv); dl.origin += fv * 18; dl.radius = 200 + (Sys.Random() & 31); dl.minlight = 32; dl.die = (float)cl.time + 0.1f; } if ((ent.effects & EntityEffects.EF_BRIGHTLIGHT) != 0) { dlight_t dl = AllocDlight(i); dl.origin = ent.origin; dl.origin.Z += 16; dl.radius = 400 + (Sys.Random() & 31); dl.die = (float)cl.time + 0.001f; } if ((ent.effects & EntityEffects.EF_DIMLIGHT) != 0) { dlight_t dl = AllocDlight(i); dl.origin = ent.origin; dl.radius = 200 + (Sys.Random() & 31); dl.die = (float)cl.time + 0.001f; } if ((ent.model.flags & EF.EF_GIB) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 2); } else if ((ent.model.flags & EF.EF_ZOMGIB) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 4); } else if ((ent.model.flags & EF.EF_TRACER) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 3); } else if ((ent.model.flags & EF.EF_TRACER2) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 5); } else if ((ent.model.flags & EF.EF_ROCKET) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 0); dlight_t dl = AllocDlight(i); dl.origin = ent.origin; dl.radius = 200; dl.die = (float)cl.time + 0.01f; } else if ((ent.model.flags & EF.EF_GRENADE) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 1); } else if ((ent.model.flags & EF.EF_TRACER3) != 0) { Render.RocketTrail(ref oldorg, ref ent.origin, 6); } ent.forcelink = false; if (i == cl.viewentity && !Chase.IsActive) { continue; } if (NumVisEdicts < MAX_VISEDICTS) { _VisEdicts[NumVisEdicts] = ent; NumVisEdicts++; } } }
/// <summary> /// CL_ParseUpdate /// /// Parse an entity update message from the server /// If an entities model or origin changes from frame to frame, it must be /// relinked. Other attributes can change without relinking. /// </summary> static void ParseUpdate(int bits) { int i; if (cls.signon == SIGNONS - 1) { // first update is the final signon stage cls.signon = SIGNONS; SignonReply(); } if ((bits & Protocol.U_MOREBITS) != 0) { i = Net.Reader.ReadByte(); bits |= (i << 8); } int num; if ((bits & Protocol.U_LONGENTITY) != 0) { num = Net.Reader.ReadShort(); } else { num = Net.Reader.ReadByte(); } entity_t ent = EntityNum(num); for (i = 0; i < 16; i++) { if ((bits & (1 << i)) != 0) { _BitCounts[i]++; } } bool forcelink = false; if (ent.msgtime != cl.mtime[1]) { forcelink = true; // no previous frame to lerp from } ent.msgtime = cl.mtime[0]; int modnum; if ((bits & Protocol.U_MODEL) != 0) { modnum = Net.Reader.ReadByte(); if (modnum >= QDef.MAX_MODELS) { Host.Error("CL_ParseModel: bad modnum"); } } else { modnum = ent.baseline.modelindex; } model_t model = cl.model_precache[modnum]; if (model != ent.model) { ent.model = model; // automatic animation (torches, etc) can be either all together // or randomized if (model != null) { if (model.synctype == synctype_t.ST_RAND) { ent.syncbase = (float)(Sys.Random() & 0x7fff) / 0x7fff; } else { ent.syncbase = 0; } if (model.numframes < ent.Pose1) { ent.Pose1 = 0; ent.Pose2 = 0; } } else { forcelink = true; // hack to make null model players work ent.Pose1 = 0; } if (num > 0 && num <= cl.maxclients) { Render.TranslatePlayerSkin(num - 1); } } if ((bits & Protocol.U_FRAME) != 0) { ent.frame = Net.Reader.ReadByte(); } else { ent.frame = ent.baseline.frame; } if ((bits & Protocol.U_COLORMAP) != 0) { i = Net.Reader.ReadByte(); } else { i = ent.baseline.colormap; } if (i == 0) { ent.colormap = Scr.vid.colormap; } else { if (i > cl.maxclients) { Sys.Error("i >= cl.maxclients"); } ent.colormap = cl.scores[i - 1].translations; } int skin; if ((bits & Protocol.U_SKIN) != 0) { skin = Net.Reader.ReadByte(); } else { skin = ent.baseline.skin; } if (skin != ent.skinnum) { ent.skinnum = skin; if (num > 0 && num <= cl.maxclients) { Render.TranslatePlayerSkin(num - 1); } } if ((bits & Protocol.U_EFFECTS) != 0) { ent.effects = Net.Reader.ReadByte(); } else { ent.effects = ent.baseline.effects; } // shift the known values for interpolation ent.msg_origins[1] = ent.msg_origins[0]; ent.msg_angles[1] = ent.msg_angles[0]; if ((bits & Protocol.U_ORIGIN1) != 0) { ent.msg_origins[0].X = Net.Reader.ReadCoord(); } else { ent.msg_origins[0].X = ent.baseline.origin.x; } if ((bits & Protocol.U_ANGLE1) != 0) { ent.msg_angles[0].X = Net.Reader.ReadAngle(); } else { ent.msg_angles[0].X = ent.baseline.angles.x; } if ((bits & Protocol.U_ORIGIN2) != 0) { ent.msg_origins[0].Y = Net.Reader.ReadCoord(); } else { ent.msg_origins[0].Y = ent.baseline.origin.y; } if ((bits & Protocol.U_ANGLE2) != 0) { ent.msg_angles[0].Y = Net.Reader.ReadAngle(); } else { ent.msg_angles[0].Y = ent.baseline.angles.y; } if ((bits & Protocol.U_ORIGIN3) != 0) { ent.msg_origins[0].Z = Net.Reader.ReadCoord(); } else { ent.msg_origins[0].Z = ent.baseline.origin.z; } if ((bits & Protocol.U_ANGLE3) != 0) { ent.msg_angles[0].Z = Net.Reader.ReadAngle(); } else { ent.msg_angles[0].Z = ent.baseline.angles.z; } if ((bits & Protocol.U_NOLERP) != 0) { ent.forcelink = true; } if (forcelink) { // didn't have an update last message ent.msg_origins[1] = ent.msg_origins[0]; ent.origin = ent.msg_origins[0]; ent.msg_angles[1] = ent.msg_angles[0]; ent.angles = ent.msg_angles[0]; ent.forcelink = true; } }
// _Host_Frame // //Runs all active servers static void InternalFrame(double time) { // keep the random time dependent Sys.Random(); // decide the simulation time if (!FilterTime(time)) { return; // don't run too fast, or packets will flood out } // get new key events Sys.SendKeyEvents(); // allow mice or other external controllers to add commands Input.Commands(); // process console commands Cbuf.Execute(); Net.Poll(); // if running the server locally, make intentions now if (Server.sv.active) { Client.SendCmd(); } //------------------- // // server operations // //------------------- // check for commands typed to the host GetConsoleCommands(); if (Server.sv.active) { ServerFrame(); } //------------------- // // client operations // //------------------- // if running the server remotely, send intentions now after // the incoming messages have been read if (!Server.sv.active) { Client.SendCmd(); } _Time += FrameTime; // fetch results from server if (Client.cls.state == cactive_t.ca_connected) { Client.ReadFromServer(); } // update video if (_Speeds.Value != 0) { _Time1 = Sys.GetFloatTime(); } Scr.UpdateScreen(); if (_Speeds.Value != 0) { _Time2 = Sys.GetFloatTime(); } // update audio if (Client.cls.signon == Client.SIGNONS) { Sound.Update(ref Render.Origin, ref Render.ViewPn, ref Render.ViewRight, ref Render.ViewUp); Client.DecayLights(); } else { Sound.Update(ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector, ref Common.ZeroVector); } CDAudio.Update(); if (_Speeds.Value != 0) { int pass1 = (int)((_Time1 - _Time3) * 1000); _Time3 = Sys.GetFloatTime(); int pass2 = (int)((_Time2 - _Time1) * 1000); int pass3 = (int)((_Time3 - _Time2) * 1000); Con.Print("{0,3} tot {1,3} server {2,3} gfx {3,3} snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } _FrameCount++; }