/// <summary> /// SV_NewChaseDir /// </summary> private void NewChaseDir(MemoryEdict actor, MemoryEdict enemy, Single dist) { var olddir = MathLib.AngleMod(( Int32 )(actor.v.ideal_yaw / 45) * 45); var turnaround = MathLib.AngleMod(olddir - 180); var deltax = enemy.v.origin.x - actor.v.origin.x; var deltay = enemy.v.origin.y - actor.v.origin.y; var d = SetupChaseDirection(deltax, deltay); // try direct route if (!TryDirectChaseRoute(d, turnaround, actor, dist)) { return; } // try other directions if (!TryAlternateChaseRoute(d, turnaround, actor, dist, deltax, deltay)) { return; } // there is no direct path to the player, so pick another direction if (olddir != DI_NODIR && StepDirection(actor, olddir, dist)) { return; } // Randomly determine direction of search if (!TryRandomChaseDir(turnaround, actor, 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); } }
/// <summary> /// SV_NewChaseDir /// </summary> private void NewChaseDir(MemoryEdict actor, MemoryEdict enemy, Single dist) { var olddir = MathLib.AngleMod(( Int32 )(actor.v.ideal_yaw / 45) * 45); var turnaround = MathLib.AngleMod(olddir - 180); var deltax = enemy.v.origin.x - actor.v.origin.x; var deltay = enemy.v.origin.y - actor.v.origin.y; Vector3f 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 Single 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 (((MathLib.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 ((MathLib.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); } }
/// <summary> /// SV_NewChaseDir /// </summary> private void NewChaseDir(MemoryEdict actor, MemoryEdict enemy, float dist) { var olddir = MathLib.AngleMod(( int )(actor.v.ideal_yaw / 45) * 45); var turnaround = MathLib.AngleMod(olddir - 180); var deltax = enemy.v.origin.X - actor.v.origin.X; var deltay = enemy.v.origin.Y - actor.v.origin.Y; Vector3 d; if (deltax > 10) { d.Y = 0; } else if (deltax < -10) { d.Y = 180; } else { d.Y = server.DI_NODIR; } if (deltay < -10) { d.Z = 270; } else if (deltay > 10) { d.Z = 90; } else { d.Z = server.DI_NODIR; } // try direct route float tdir; if (d.Y != server.DI_NODIR && d.Z != server.DI_NODIR) { if (d.Y == 0) { tdir = d.Z == 90 ? 45 : 315; } else { tdir = d.Z == 90 ? 135 : 215; } if (tdir != turnaround && this.StepDirection(actor, tdir, dist)) { return; } } // try other directions if ((MathLib.Random() & 3 & 1) != 0 || Math.Abs(deltay) > Math.Abs(deltax)) { tdir = d.Y; d.Y = d.Z; d.Z = tdir; } if (d.Y != server.DI_NODIR && d.Y != turnaround && this.StepDirection(actor, d.Y, dist)) { return; } if (d.Z != server.DI_NODIR && d.Z != turnaround && this.StepDirection(actor, d.Z, dist)) { return; } // there is no direct path to the player, so pick another direction if (olddir != server.DI_NODIR && this.StepDirection(actor, olddir, dist)) { return; } if ((MathLib.Random() & 1) != 0) //randomly determine direction of search { for (tdir = 0; tdir <= 315; tdir += 45) { if (tdir != turnaround && this.StepDirection(actor, tdir, dist)) { return; } } } else { for (tdir = 315; tdir >= 0; tdir -= 45) { if (tdir != turnaround && this.StepDirection(actor, tdir, dist)) { return; } } } if (turnaround != server.DI_NODIR && this.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 (!this.CheckBottom(actor)) { this.FixCheckBottom(actor); } }
/// <summary> /// CL_RelinkEntities /// </summary> private void RelinkEntities() { // determine partial update time var frac = this.LerpPoint(); this.NumVisEdicts = 0; // // interpolate player info // this.cl.velocity = this.cl.mvelocity[1] + frac * (this.cl.mvelocity[0] - this.cl.mvelocity[1]); if (this.cls.demoplayback) { // interpolate the angles var angleDelta = this.cl.mviewangles[0] - this.cl.mviewangles[1]; MathLib.CorrectAngles180(ref angleDelta); this.cl.viewangles = this.cl.mviewangles[1] + frac * angleDelta; } var bobjrotate = MathLib.AngleMod(100 * this.cl.time); // start on the entity after the world for (var i = 1; i < this.cl.num_entities; i++) { var ent = this._Entities[i]; if (ent.model == null) { // empty slot if (ent.forcelink) { this.Host.RenderContext.RemoveEfrags(ent); // just became empty } continue; } // if the object wasn't included in the last packet, remove it if (ent.msgtime != this.cl.mtime[0]) { ent.model = null; continue; } var 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 var f = frac; var 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 } // interpolate the origin and angles ent.origin = ent.msg_origins[1] + f * delta; var 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.HasFlag(EntityFlags.Rotate)) { ent.angles.Y = bobjrotate; } if ((ent.effects & EntityEffects.EF_BRIGHTFIELD) != 0) { this.Host.RenderContext.Particles.EntityParticles(this.Host.Client.cl.time, ent.origin); } if ((ent.effects & EntityEffects.EF_MUZZLEFLASH) != 0) { var dl = this.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 + (MathLib.Random() & 31); dl.minlight = 32; dl.die = ( float )this.cl.time + 0.1f; } if ((ent.effects & EntityEffects.EF_BRIGHTLIGHT) != 0) { var dl = this.AllocDlight(i); dl.origin = ent.origin; dl.origin.Z += 16; dl.radius = 400 + (MathLib.Random() & 31); dl.die = ( float )this.cl.time + 0.001f; } if ((ent.effects & EntityEffects.EF_DIMLIGHT) != 0) { var dl = this.AllocDlight(i); dl.origin = ent.origin; dl.radius = 200 + (MathLib.Random() & 31); dl.die = ( float )this.cl.time + 0.001f; } if (ent.model.Flags.HasFlag(EntityFlags.Gib)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 2); } else if (ent.model.Flags.HasFlag(EntityFlags.ZomGib)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 4); } else if (ent.model.Flags.HasFlag(EntityFlags.Tracer)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 3); } else if (ent.model.Flags.HasFlag(EntityFlags.Tracer2)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 5); } else if (ent.model.Flags.HasFlag(EntityFlags.Rocket)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 0); var dl = this.AllocDlight(i); dl.origin = ent.origin; dl.radius = 200; dl.die = ( float )this.cl.time + 0.01f; } else if (ent.model.Flags.HasFlag(EntityFlags.Grenade)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 1); } else if (ent.model.Flags.HasFlag(EntityFlags.Tracer3)) { this.Host.RenderContext.Particles.RocketTrail(this.Host.Client.cl.time, ref oldorg, ref ent.origin, 6); } ent.forcelink = false; if (i == this.cl.viewentity && !this.Host.ChaseView.IsActive) { continue; } if (this.NumVisEdicts < ClientDef.MAX_VISEDICTS) { this._VisEdicts[this.NumVisEdicts] = ent; this.NumVisEdicts++; } } }