static void Test5_f() { entity_t p = Client.ViewEntity; if (p == null) { return; } OpenTK.Vector3 org = p.origin; for (int i = 0; i < Server.sv.edicts.Length; i++) { edict_t ed = Server.sv.edicts[i]; if (ed.free) { continue; } OpenTK.Vector3 vmin, vmax; Mathlib.Copy(ref ed.v.absmax, out vmax); Mathlib.Copy(ref ed.v.absmin, out vmin); if (org.X >= vmin.X && org.Y >= vmin.Y && org.Z >= vmin.Z && org.X <= vmax.X && org.Y <= vmax.Y && org.Z <= vmax.Z) { Con.Print("{0}\n", i); } } }
/// <summary> /// PushEntity /// Does not change the entities velocity at all /// </summary> private static trace_t PushEntity(edict_t ent, ref v3f push) { v3f end; Mathlib.VectorAdd(ref ent.v.origin, ref push, out end); trace_t trace; if (ent.v.movetype == Movetypes.MOVETYPE_FLYMISSILE) { trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_MISSILE, ent); } else if (ent.v.solid == Solids.SOLID_TRIGGER || ent.v.solid == Solids.SOLID_NOT) { // only clip against bmodels trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_NOMONSTERS, ent); } else { trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_NORMAL, ent); } Mathlib.Copy(ref trace.endpos, out ent.v.origin); LinkEdict(ent, true); if (trace.ent != null) { Impact(ent, trace.ent); } return(trace); }
/* * =============== * PF_droptofloor * * void() droptofloor * =============== */ static void PF_droptofloor() { edict_t ent = Server.ProgToEdict(Progs.GlobalStruct.self); Vector3 org, mins, maxs; Mathlib.Copy(ref ent.v.origin, out org); Mathlib.Copy(ref ent.v.mins, out mins); Mathlib.Copy(ref ent.v.maxs, out maxs); Vector3 end = org; end.Z -= 256; trace_t trace = Server.Move(ref org, ref mins, ref maxs, ref end, 0, ent); if (trace.fraction == 1 || trace.allsolid) { ReturnFloat(0); } else { Mathlib.Copy(ref trace.endpos, out ent.v.origin); Server.LinkEdict(ent, false); ent.v.flags = (int)ent.v.flags | EdictFlags.FL_ONGROUND; ent.v.groundentity = Server.EdictToProg(trace.ent); ReturnFloat(1); } }
/* * ================= * PF_traceline * * Used for use tracing and shot targeting * Traces are blocked by bbox and exact bsp entityes, and also slide box entities * if the tryents flag is set. * * traceline (vector1, vector2, tryents) * ================= */ static unsafe void PF_traceline() { float * v1 = GetVector(OFS.OFS_PARM0); float * v2 = GetVector(OFS.OFS_PARM1); int nomonsters = (int)GetFloat(OFS.OFS_PARM2); edict_t ent = GetEdict(OFS.OFS_PARM3); Vector3 vec1, vec2; Copy(v1, out vec1); Copy(v2, out vec2); trace_t trace = Server.Move(ref vec1, ref Common.ZeroVector, ref Common.ZeroVector, ref vec2, nomonsters, ent); Progs.GlobalStruct.trace_allsolid = trace.allsolid ? 1 : 0; Progs.GlobalStruct.trace_startsolid = trace.startsolid ? 1 : 0; Progs.GlobalStruct.trace_fraction = trace.fraction; Progs.GlobalStruct.trace_inwater = trace.inwater ? 1 : 0; Progs.GlobalStruct.trace_inopen = trace.inopen ? 1 : 0; Mathlib.Copy(ref trace.endpos, out Progs.GlobalStruct.trace_endpos); Mathlib.Copy(ref trace.plane.normal, out Progs.GlobalStruct.trace_plane_normal); Progs.GlobalStruct.trace_plane_dist = trace.plane.dist; if (trace.ent != null) { Progs.GlobalStruct.trace_ent = Server.EdictToProg(trace.ent); } else { Progs.GlobalStruct.trace_ent = Server.EdictToProg(Server.sv.edicts[0]); } }
/// <summary> /// SV_ReadClientMove /// </summary> static void ReadClientMove(ref usercmd_t move) { client_t client = Host.HostClient; // read ping time client.ping_times[client.num_pings % NUM_PING_TIMES] = (float)(sv.time - Net.Reader.ReadFloat()); client.num_pings++; // read current angles Vector3 angles = Net.Reader.ReadAngles(); Mathlib.Copy(ref angles, out client.edict.v.v_angle); // read movement move.forwardmove = Net.Reader.ReadShort(); move.sidemove = Net.Reader.ReadShort(); move.upmove = Net.Reader.ReadShort(); // read buttons int bits = Net.Reader.ReadByte(); client.edict.v.button0 = bits & 1; client.edict.v.button2 = (bits & 2) >> 1; int i = Net.Reader.ReadByte(); if (i != 0) { client.edict.v.impulse = i; } }
static trace_t Move(ref v3f start, ref v3f mins, ref v3f maxs, ref v3f end, int type, edict_t passedict) { Vector3 vstart, vmins, vmaxs, vend; Mathlib.Copy(ref start, out vstart); Mathlib.Copy(ref mins, out vmins); Mathlib.Copy(ref maxs, out vmaxs); Mathlib.Copy(ref end, out vend); return(Move(ref vstart, ref vmins, ref vmaxs, ref vend, type, passedict)); }
/* * ============== * 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); }
static void DropPunchAngle() { Vector3 v = Common.ToVector(ref _Player.v.punchangle); double len = Mathlib.Normalize(ref v) - 10 * Host.FrameTime; if (len < 0) { len = 0; } v *= (float)len; Mathlib.Copy(ref v, out _Player.v.punchangle); }
/// <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> /// SV_FlyMove /// The basic solid body movement clip that slides along multiple planes /// Returns the clipflags if the velocity was modified (hit something solid) /// 1 = floor /// 2 = wall / step /// 4 = dead stop /// If steptrace is not NULL, the trace of any vertical wall hit will be stored /// </summary> static int FlyMove(edict_t ent, float time, trace_t steptrace) { v3f original_velocity = ent.v.velocity; v3f primal_velocity = ent.v.velocity; int numbumps = 4; int blocked = 0; Vector3[] planes = new Vector3[MAX_CLIP_PLANES]; int numplanes = 0; float time_left = time; for (int bumpcount = 0; bumpcount < numbumps; bumpcount++) { if (ent.v.velocity.IsEmpty) { break; } v3f end; Mathlib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end); trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid) { // entity is trapped in another solid ent.v.velocity = default(v3f); return(3); } if (trace.fraction > 0) { // actually covered some distance Mathlib.Copy(ref trace.endpos, out ent.v.origin); original_velocity = ent.v.velocity; numplanes = 0; } if (trace.fraction == 1) { break; // moved the entire distance } if (trace.ent == null) { Sys.Error("SV_FlyMove: !trace.ent"); } if (trace.plane.normal.Z > 0.7) { blocked |= 1; // floor if (trace.ent.v.solid == Solids.SOLID_BSP) { ent.v.flags = (int)ent.v.flags | EdictFlags.FL_ONGROUND; ent.v.groundentity = EdictToProg(trace.ent); } } if (trace.plane.normal.Z == 0) { blocked |= 2; // step if (steptrace != null) { steptrace.CopyFrom(trace); // save for player extrafriction } } // // run the impact function // Impact(ent, trace.ent); if (ent.free) { break; // removed by the impact function } time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen ent.v.velocity = default(v3f); return(3); } planes[numplanes] = trace.plane.normal; numplanes++; // // modify original_velocity so it parallels all of the clip planes // v3f new_velocity = default(v3f); int i, j; for (i = 0; i < numplanes; i++) { ClipVelocity(ref original_velocity, ref planes[i], out new_velocity, 1); for (j = 0; j < numplanes; j++) { if (j != i) { float dot = new_velocity.x * planes[j].X + new_velocity.y * planes[j].Y + new_velocity.z * planes[j].Z; if (dot < 0) { break; // not ok } } } if (j == numplanes) { break; } } if (i != numplanes) { // go along this plane ent.v.velocity = new_velocity; } else { // go along the crease if (numplanes != 2) { ent.v.velocity = default(v3f); return(7); } Vector3 dir = Vector3.Cross(planes[0], planes[1]); float d = dir.X * ent.v.velocity.x + dir.Y * ent.v.velocity.y + dir.Z * ent.v.velocity.z; Mathlib.Copy(ref dir, out ent.v.velocity); Mathlib.VectorScale(ref ent.v.velocity, d, out ent.v.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Mathlib.DotProduct(ref ent.v.velocity, ref primal_velocity) <= 0) { ent.v.velocity = default(v3f); return(blocked); } } return(blocked); }
static void SetMinMaxSize(edict_t e, ref Vector3 min, ref Vector3 max, bool rotate) { if (min.X > max.X || min.Y > max.Y || min.Z > max.Z) { Progs.RunError("backwards mins/maxs"); } rotate = false; // FIXME: implement rotation properly again Vector3 rmin = min, rmax = max; if (!rotate) { //rmin = min; //rmax = max; } else { // find min / max for rotations //angles = e.v.angles; //a = angles[1] / 180 * M_PI; //xvector[0] = cos(a); //xvector[1] = sin(a); //yvector[0] = -sin(a); //yvector[1] = cos(a); //VectorCopy(min, bounds[0]); //VectorCopy(max, bounds[1]); //rmin[0] = rmin[1] = rmin[2] = 9999; //rmax[0] = rmax[1] = rmax[2] = -9999; //for (i = 0; i <= 1; i++) //{ // base[0] = bounds[i][0]; // for (j = 0; j <= 1; j++) // { // base[1] = bounds[j][1]; // for (k = 0; k <= 1; k++) // { // base[2] = bounds[k][2]; // // transform the point // transformed[0] = xvector[0] * base[0] + yvector[0] * base[1]; // transformed[1] = xvector[1] * base[0] + yvector[1] * base[1]; // transformed[2] = base[2]; // for (l = 0; l < 3; l++) // { // if (transformed[l] < rmin[l]) // rmin[l] = transformed[l]; // if (transformed[l] > rmax[l]) // rmax[l] = transformed[l]; // } // } // } //} } // set derived values Mathlib.Copy(ref rmin, out e.v.mins); Mathlib.Copy(ref rmax, out e.v.maxs); Vector3 s = max - min; Mathlib.Copy(ref s, out e.v.size); Server.LinkEdict(e, false); }
/* * ============= * PF_aim * * Pick a vector for the player to shoot along * vector aim(entity, missilespeed) * ============= */ static void PF_aim() { edict_t ent = GetEdict(OFS.OFS_PARM0); float speed = GetFloat(OFS.OFS_PARM1); Vector3 start = Common.ToVector(ref ent.v.origin); start.Z += 20; // try sending a trace straight Vector3 dir; Mathlib.Copy(ref Progs.GlobalStruct.v_forward, out dir); Vector3 end = start + dir * 2048; trace_t tr = Server.Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref end, 0, ent); if (tr.ent != null && tr.ent.v.takedamage == Damages.DAMAGE_AIM && (Host.TeamPlay == 0 || ent.v.team <= 0 || ent.v.team != tr.ent.v.team)) { ReturnVector(ref Progs.GlobalStruct.v_forward); return; } // try all possible entities Vector3 bestdir = dir; float bestdist = Server.Aim; edict_t bestent = null; for (int i = 1; i < Server.sv.num_edicts; i++) { edict_t check = Server.sv.edicts[i]; if (check.v.takedamage != Damages.DAMAGE_AIM) { continue; } if (check == ent) { continue; } if (Host.TeamPlay != 0 && ent.v.team > 0 && ent.v.team == check.v.team) { continue; // don't aim at teammate } v3f tmp; Mathlib.VectorAdd(ref check.v.mins, ref check.v.maxs, out tmp); Mathlib.VectorMA(ref check.v.origin, 0.5f, ref tmp, out tmp); Mathlib.Copy(ref tmp, out end); dir = end - start; Mathlib.Normalize(ref dir); float dist = Vector3.Dot(dir, Common.ToVector(ref Progs.GlobalStruct.v_forward)); if (dist < bestdist) { continue; // to far to turn } tr = Server.Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref end, 0, ent); if (tr.ent == check) { // can shoot at this one bestdist = dist; bestent = check; } } if (bestent != null) { v3f dir2, end2; Mathlib.VectorSubtract(ref bestent.v.origin, ref ent.v.origin, out dir2); float dist = Mathlib.DotProduct(ref dir2, ref Progs.GlobalStruct.v_forward); Mathlib.VectorScale(ref Progs.GlobalStruct.v_forward, dist, out end2); end2.z = dir2.z; Mathlib.Normalize(ref end2); ReturnVector(ref end2); } else { ReturnVector(ref bestdir); } }
/// <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); }