/// <summary> /// SV_movestep /// Called by monster program code. /// The move will be adjusted for slopes and stairs, but if the move isn't /// possible, no move is done, false is returned, and /// pr_global_struct.trace_normal is set to the normal of the blocking wall /// </summary> public static bool MoveStep(edict_t ent, ref v3f move, bool relink) { trace_t trace; // try the move v3f oldorg = ent.v.origin; v3f neworg; Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg); // flying monsters don't step up if (((int)ent.v.flags & (EdictFlags.FL_SWIM | EdictFlags.FL_FLY)) != 0) { // try one move with vertical motion, then one without for (int i = 0; i < 2; i++) { Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg); edict_t enemy = ProgToEdict(ent.v.enemy); if (i == 0 && enemy != sv.edicts[0]) { float dz = ent.v.origin.z - enemy.v.origin.z; if (dz > 40) { neworg.z -= 8; } if (dz < 30) { neworg.z += 8; } } trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref neworg, 0, ent); if (trace.fraction == 1) { if (((int)ent.v.flags & EdictFlags.FL_SWIM) != 0 && PointContents(ref trace.endpos) == Contents.CONTENTS_EMPTY) { return(false); // swim monster left water } Mathlib.Copy(ref trace.endpos, out ent.v.origin); if (relink) { LinkEdict(ent, true); } return(true); } if (enemy == sv.edicts[0]) { break; } } return(false); } // push down from a step height above the wished position neworg.z += STEPSIZE; v3f end = neworg; end.z -= STEPSIZE * 2; trace = Move(ref neworg, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid) { return(false); } if (trace.startsolid) { neworg.z -= STEPSIZE; trace = Move(ref neworg, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid || trace.startsolid) { return(false); } } if (trace.fraction == 1) { // if monster had the ground pulled out, go ahead and fall if (((int)ent.v.flags & EdictFlags.FL_PARTIALGROUND) != 0) { Mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin); if (relink) { LinkEdict(ent, true); } ent.v.flags = (int)ent.v.flags & ~EdictFlags.FL_ONGROUND; return(true); } return(false); // walked off an edge } // check point traces down for dangling corners Mathlib.Copy(ref trace.endpos, out ent.v.origin); if (!CheckBottom(ent)) { if (((int)ent.v.flags & EdictFlags.FL_PARTIALGROUND) != 0) { // entity had floor mostly pulled out from underneath it // and is trying to correct if (relink) { LinkEdict(ent, true); } return(true); } ent.v.origin = oldorg; return(false); } if (((int)ent.v.flags & EdictFlags.FL_PARTIALGROUND) != 0) { ent.v.flags = (int)ent.v.flags & ~EdictFlags.FL_PARTIALGROUND; } ent.v.groundentity = EdictToProg(trace.ent); // the move is ok if (relink) { LinkEdict(ent, true); } return(true); }
static unsafe void Copy(float *src, ref v3f dest) { dest.x = src[0]; dest.y = src[1]; dest.z = src[2]; }
public static void Copy(ref Vector3 src, out v3f dest) { dest.x = src.X; dest.y = src.Y; dest.z = src.Z; }
public static float LengthXY(ref v3f v) { return((float)Math.Sqrt(v.x * v.x + v.y * v.y)); }
public static float DotProduct(ref v3f a, ref v3f b) { return(a.x * b.x + a.y * b.y + a.z * b.z); }
//static Vector3 PerpendicularVector(ref Vector3 src) //{ // float minelem = 1.0f; // // find the smallest magnitude axially aligned vector // Vector3 tempvec = Vector3.Zero; // if (Math.Abs(src.X) < minelem) // { // minelem = Math.Abs(src.X); // tempvec.X = 1; // } // if (Math.Abs(src.Y) < minelem) // { // minelem = Math.Abs(src.Y); // tempvec = new Vector3(0, 1, 0); // } // else if (Math.Abs(src.Z) < minelem) // { // tempvec = new Vector3(0, 0, 1); // } // // project the point onto the plane defined by src // Vector3 dst = ProjectPointOnPlane(ref tempvec, ref src); // Normalize(ref dst); // return dst; //} //static Vector3 ProjectPointOnPlane(ref Vector3 p, ref Vector3 normal) //{ // float inv_denom = 1.0f / normal.LengthSquared; // float d = Vector3.Dot(normal, p) * inv_denom; // Vector3 n = normal * inv_denom; // return p - d * n; //} public static void Copy(ref v3f src, out Vector3 dest) { dest.X = src.x; dest.Y = src.y; dest.Z = src.z; }
public static void VectorSubtract(ref byte[] a, ref byte[] b, out v3f c) { c.x = a[0] - b[0]; c.y = a[1] - b[1]; c.z = a[2] - b[2]; }
public static void Clamp(ref v3f src, ref Vector3 min, ref Vector3 max, out v3f dest) { dest.x = Math.Max(Math.Min(src.x, max.X), min.X); dest.y = Math.Max(Math.Min(src.y, max.Y), min.Y); dest.z = Math.Max(Math.Min(src.z, max.Z), min.Z); }
public static void VectorSubtract(ref v3f a, ref v3f b, out v3f c) { c.x = a.x - b.x; c.y = a.y - b.y; c.z = a.z - b.z; }
public static void VectorAdd(ref v3f a, ref v3f b, out v3f c) { c.x = a.x + b.x; c.y = a.y + b.y; c.z = a.z + b.z; }
public static void VectorScale(ref v3f a, float scale, out v3f b) { b.x = a.x * scale; b.y = a.y * scale; b.z = a.z * scale; }
/// <summary> /// c = a + b * scale; /// </summary> public static void VectorMA(ref v3f a, float scale, ref v3f b, out v3f c) { c.x = a.x + b.x * scale; c.y = a.y + b.y * scale; c.z = a.z + b.z * scale; }
/// <summary> /// SV_SetIdealPitch /// </summary> public static void SetIdealPitch() { if (((int)_Player.v.flags & EdictFlags.FL_ONGROUND) == 0) { return; } double angleval = _Player.v.angles.y * Math.PI * 2 / 360; double sinval = Math.Sin(angleval); double cosval = Math.Cos(angleval); float[] z = new float[MAX_FORWARD]; for (int i = 0; i < MAX_FORWARD; i++) { v3f top = _Player.v.origin; top.x += (float)(cosval * (i + 3) * 12); top.y += (float)(sinval * (i + 3) * 12); top.z += _Player.v.view_ofs.z; v3f bottom = top; bottom.z -= 160; trace_t tr = Move(ref top, ref Common.ZeroVector3f, ref Common.ZeroVector3f, ref bottom, 1, _Player); if (tr.allsolid) { return; // looking at a wall, leave ideal the way is was } if (tr.fraction == 1) { return; // near a dropoff } z[i] = top.z + tr.fraction * (bottom.z - top.z); } float dir = 0; // Uze: int in original code??? int steps = 0; for (int j = 1; j < MAX_FORWARD; j++) { float step = z[j] - z[j - 1]; // Uze: int in original code??? if (step > -QDef.ON_EPSILON && step < QDef.ON_EPSILON) // Uze: comparing int with ON_EPSILON (0.1)??? { continue; } if (dir != 0 && (step - dir > QDef.ON_EPSILON || step - dir < -QDef.ON_EPSILON)) { return; // mixed changes } steps++; dir = step; } if (dir == 0) { _Player.v.idealpitch = 0; return; } if (steps < 2) { return; } _Player.v.idealpitch = -dir * _IdealPitchScale.Value; }