// Chase_Update public static void Update() { // if can't see player, reset Vector3 forward, up, right; Mathlib.AngleVectors(ref Client.cl.viewangles, out forward, out right, out up); // calc exact destination _Dest = Render.RefDef.vieworg - forward * _Back.Value - right * _Right.Value; _Dest.Z = Render.RefDef.vieworg.Z + _Up.Value; // find the spot the player is looking at Vector3 dest = Render.RefDef.vieworg + forward * 4096; Vector3 stop; TraceLine(ref Render.RefDef.vieworg, ref dest, out stop); // calculate pitch to look at the same spot from camera stop -= Render.RefDef.vieworg; float dist; Vector3.Dot(ref stop, ref forward, out dist); if (dist < 1) { dist = 1; } Render.RefDef.viewangles.X = (float)(-Math.Atan(stop.Z / dist) / Math.PI * 180.0); //r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180; // move towards destination Render.RefDef.vieworg = _Dest; //VectorCopy(chase_dest, r_refdef.vieworg); }
/* * ============== * PF_makevectors * * Writes new values for v_forward, v_up, and v_right based on angles * makevectors(vector) * ============== */ static unsafe void PF_makevectors() { float * av = GetVector(OFS.OFS_PARM0); Vector3 a = new Vector3(av[0], av[1], av[2]); Vector3 fw, right, up; Mathlib.AngleVectors(ref a, out fw, out right, out up); Mathlib.Copy(ref fw, out Progs.GlobalStruct.v_forward); Mathlib.Copy(ref right, out Progs.GlobalStruct.v_right); Mathlib.Copy(ref up, out Progs.GlobalStruct.v_up); }
/// <summary> /// SV_AirMove /// </summary> static void AirMove() { Vector3 pangles = Common.ToVector(ref _Player.v.angles); Mathlib.AngleVectors(ref pangles, out _Forward, out _Right, out _Up); float fmove = _Cmd.forwardmove; float smove = _Cmd.sidemove; // hack to not let you back into teleporter if (sv.time < _Player.v.teleport_time && fmove < 0) { fmove = 0; } Vector3 wishvel = _Forward * fmove + _Right * smove; if ((int)_Player.v.movetype != Movetypes.MOVETYPE_WALK) { wishvel.Z = _Cmd.upmove; } else { wishvel.Z = 0; } _WishDir = wishvel; _WishSpeed = Mathlib.Normalize(ref _WishDir); if (_WishSpeed > _MaxSpeed.Value) { wishvel *= _MaxSpeed.Value / _WishSpeed; _WishSpeed = _MaxSpeed.Value; } if (_Player.v.movetype == Movetypes.MOVETYPE_NOCLIP) { // noclip Mathlib.Copy(ref wishvel, out _Player.v.velocity); } else if (_OnGround) { UserFriction(); Accelerate(); } else { // not on ground, so little effect on velocity AirAccelerate(wishvel); } }
/// <summary> /// V_CalcRoll /// Used by view and sv_user /// </summary> public static float CalcRoll(ref Vector3 angles, ref Vector3 velocity) { Mathlib.AngleVectors(ref angles, out _Forward, out _Right, out _Up); float side = Vector3.Dot(velocity, _Right); float sign = side < 0 ? -1 : 1; side = Math.Abs(side); float value = _ClRollAngle.Value; if (side < _ClRollSpeed.Value) { side = side * value / _ClRollSpeed.Value; } else { side = value; } return(side * sign); }
/// <summary> /// SV_WallFriction /// </summary> static void WallFriction(edict_t ent, trace_t trace) { Vector3 forward, right, up, vangle = Common.ToVector(ref ent.v.v_angle); Mathlib.AngleVectors(ref vangle, out forward, out right, out up); float d = Vector3.Dot(trace.plane.normal, forward); d += 0.5f; if (d >= 0) { return; } // cut the tangential velocity Vector3 vel = Common.ToVector(ref ent.v.velocity); float i = Vector3.Dot(trace.plane.normal, vel); Vector3 into = trace.plane.normal * i; Vector3 side = vel - into; ent.v.velocity.x = side.X * (1 + d); ent.v.velocity.y = side.Y * (1 + d); }
// V_ParseDamage public static void ParseDamage() { int armor = Net.Reader.ReadByte(); int blood = Net.Reader.ReadByte(); Vector3 from = Net.Reader.ReadCoords(); float count = blood * 0.5f + armor * 0.5f; if (count < 10) { count = 10; } client_state_t cl = Client.cl; cl.faceanimtime = (float)cl.time + 0.2f; // put sbar face into pain frame cl.cshifts[ColorShift.CSHIFT_DAMAGE].percent += (int)(3 * count); if (cl.cshifts[ColorShift.CSHIFT_DAMAGE].percent < 0) { cl.cshifts[ColorShift.CSHIFT_DAMAGE].percent = 0; } if (cl.cshifts[ColorShift.CSHIFT_DAMAGE].percent > 150) { cl.cshifts[ColorShift.CSHIFT_DAMAGE].percent = 150; } if (armor > blood) { cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[0] = 200; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[1] = 100; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[2] = 100; } else if (armor != 0) { cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[0] = 220; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[1] = 50; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[2] = 50; } else { cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[0] = 255; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[1] = 0; cl.cshifts[ColorShift.CSHIFT_DAMAGE].destcolor[2] = 0; } // // calculate view angle kicks // entity_t ent = Client.Entities[cl.viewentity]; from -= ent.origin; // VectorSubtract (from, ent->origin, from); Mathlib.Normalize(ref from); Vector3 forward, right, up; Mathlib.AngleVectors(ref ent.angles, out forward, out right, out up); float side = Vector3.Dot(from, right); _DmgRoll = count * side * _KickRoll.Value; side = Vector3.Dot(from, forward); _DmgPitch = count * side * _KickPitch.Value; _DmgTime = _KickTime.Value; }
// V_CalcRefdef static void CalcRefDef() { DriftPitch(); // ent is the player model (visible when out of body) entity_t ent = Client.ViewEntity; // view is the weapon model (only visible from inside body) entity_t view = Client.ViewEnt; // transform the view offset by the model's matrix to get the offset from // model origin for the view ent.angles.Y = Client.cl.viewangles.Y; // the model should face the view dir ent.angles.X = -Client.cl.viewangles.X; // the model should face the view dir float bob = CalcBob(); refdef_t rdef = Render.RefDef; client_state_t cl = Client.cl; // refresh position rdef.vieworg = ent.origin; rdef.vieworg.Z += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis rdef.vieworg += SmallOffset; rdef.viewangles = cl.viewangles; CalcViewRoll(); AddIdle(_IdleScale.Value); // offsets Vector3 angles = ent.angles; angles.X = -angles.X; // because entity pitches are actually backward Vector3 forward, right, up; Mathlib.AngleVectors(ref angles, out forward, out right, out up); rdef.vieworg += forward * _ScrOfsX.Value + right * _ScrOfsY.Value + up * _ScrOfsZ.Value; BoundOffsets(); // set up gun position view.angles = cl.viewangles; CalcGunAngle(); view.origin = ent.origin; view.origin.Z += cl.viewheight; view.origin += forward * bob * 0.4f; view.origin.Z += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV float viewSize = Scr.ViewSize.Value; // scr_viewsize if (viewSize == 110) { view.origin.Z += 1; } else if (viewSize == 100) { view.origin.Z += 2; } else if (viewSize == 90) { view.origin.Z += 1; } else if (viewSize == 80) { view.origin.Z += 0.5f; } view.model = cl.model_precache[cl.stats[QStats.STAT_WEAPON]]; view.frame = cl.stats[QStats.STAT_WEAPONFRAME]; view.colormap = Scr.vid.colormap; // set up the refresh position rdef.viewangles += cl.punchangle; // smooth out stair step ups if (cl.onground && ent.origin.Z - _OldZ > 0) { float steptime = (float)(cl.time - cl.oldtime); if (steptime < 0) { steptime = 0; } _OldZ += steptime * 80; if (_OldZ > ent.origin.Z) { _OldZ = ent.origin.Z; } if (ent.origin.Z - _OldZ > 12) { _OldZ = ent.origin.Z - 12; } rdef.vieworg.Z += _OldZ - ent.origin.Z; view.origin.Z += _OldZ - ent.origin.Z; } else { _OldZ = ent.origin.Z; } if (Chase.IsActive) { Chase.Update(); } }
/// <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> /// R_DrawBrushModel /// </summary> private static void DrawBrushModel(entity_t e) { _CurrentEntity = e; Drawer.CurrentTexture = -1; model_t clmodel = e.model; bool rotated = false; Vector3 mins, maxs; if (e.angles.X != 0 || e.angles.Y != 0 || e.angles.Z != 0) { rotated = true; mins = e.origin; mins.X -= clmodel.radius; mins.Y -= clmodel.radius; mins.Z -= clmodel.radius; maxs = e.origin; maxs.X += clmodel.radius; maxs.Y += clmodel.radius; maxs.Z += clmodel.radius; } else { mins = e.origin + clmodel.mins; maxs = e.origin + clmodel.maxs; } if (CullBox(ref mins, ref maxs)) { return; } GL.Color3(1f, 1, 1); Array.Clear(_LightMapPolys, 0, _LightMapPolys.Length); _ModelOrg = _RefDef.vieworg - e.origin; if (rotated) { Vector3 temp = _ModelOrg; Vector3 forward, right, up; Mathlib.AngleVectors(ref e.angles, out forward, out right, out up); _ModelOrg.X = Vector3.Dot(temp, forward); _ModelOrg.Y = -Vector3.Dot(temp, right); _ModelOrg.Z = Vector3.Dot(temp, up); } // calculate dynamic lighting for bmodel if it's not an // instanced model if (clmodel.firstmodelsurface != 0 && _glFlashBlend.Value == 0) { for (int k = 0; k < Client.MAX_DLIGHTS; k++) { if ((Client.DLights[k].die < Client.cl.time) || (Client.DLights[k].radius == 0)) { continue; } MarkLights(Client.DLights[k], 1 << k, clmodel.nodes[clmodel.hulls[0].firstclipnode]); } } GL.PushMatrix(); e.angles.X = -e.angles.X; // stupid quake bug RotateForEntity(e); e.angles.X = -e.angles.X; // stupid quake bug int surfOffset = clmodel.firstmodelsurface; msurface_t[] psurf = clmodel.surfaces; //[clmodel.firstmodelsurface]; // // draw texture // for (int i = 0; i < clmodel.nummodelsurfaces; i++, surfOffset++) { // find which side of the node we are on mplane_t pplane = psurf[surfOffset].plane; float dot = Vector3.Dot(_ModelOrg, pplane.normal) - pplane.dist; // draw the polygon bool planeBack = (psurf[surfOffset].flags & Surf.SURF_PLANEBACK) != 0; if ((planeBack && (dot < -QDef.BACKFACE_EPSILON)) || (!planeBack && (dot > QDef.BACKFACE_EPSILON))) { if (_glTexSort.Value != 0) { RenderBrushPoly(psurf[surfOffset]); } else { DrawSequentialPoly(psurf[surfOffset]); } } } BlendLightmaps(); GL.PopMatrix(); }
/// <summary> /// SV_WaterMove /// </summary> static void WaterMove() { // // user intentions // Vector3 pangle = Common.ToVector(ref _Player.v.v_angle); Mathlib.AngleVectors(ref pangle, out _Forward, out _Right, out _Up); Vector3 wishvel = _Forward * _Cmd.forwardmove + _Right * _Cmd.sidemove; if (_Cmd.forwardmove == 0 && _Cmd.sidemove == 0 && _Cmd.upmove == 0) { wishvel.Z -= 60; // drift towards bottom } else { wishvel.Z += _Cmd.upmove; } float wishspeed = wishvel.Length; if (wishspeed > _MaxSpeed.Value) { wishvel *= _MaxSpeed.Value / wishspeed; wishspeed = _MaxSpeed.Value; } wishspeed *= 0.7f; // // water friction // float newspeed, speed = Mathlib.Length(ref _Player.v.velocity); if (speed != 0) { newspeed = (float)(speed - Host.FrameTime * speed * _Friction.Value); if (newspeed < 0) { newspeed = 0; } Mathlib.VectorScale(ref _Player.v.velocity, newspeed / speed, out _Player.v.velocity); } else { newspeed = 0; } // // water acceleration // if (wishspeed == 0) { return; } float addspeed = wishspeed - newspeed; if (addspeed <= 0) { return; } Mathlib.Normalize(ref wishvel); float accelspeed = (float)(_Accelerate.Value * wishspeed * Host.FrameTime); if (accelspeed > addspeed) { accelspeed = addspeed; } wishvel *= accelspeed; _Player.v.velocity.x += wishvel.X; _Player.v.velocity.y += wishvel.Y; _Player.v.velocity.z += wishvel.Z; }