/** * Does not change the entities velocity at all */ public static trace_t SV_PushEntity(edict_t ent, float[] push) { trace_t trace; float[] start = { 0, 0, 0 }; float[] end = { 0, 0, 0 }; int mask; Math3D.VectorCopy(ent.s.origin, start); Math3D.VectorAdd(start, push, end); // FIXME: test this // a goto statement was replaced. var retry = false; do { if (ent.clipmask != 0) { mask = ent.clipmask; } else { mask = Defines.MASK_SOLID; } trace = GameBase.gi.trace(start, ent.mins, ent.maxs, end, ent, mask); Math3D.VectorCopy(trace.endpos, ent.s.origin); GameBase.gi.linkentity(ent); retry = false; if (trace.fraction != 1.0) { SV.SV_Impact(ent, trace); // if the pushed entity went away and the pusher is still there if (!trace.ent.inuse && ent.inuse) { // move the pusher back and try again Math3D.VectorCopy(start, ent.s.origin); GameBase.gi.linkentity(ent); //goto retry; retry = true; } } }while (retry); if (ent.inuse) { GameBase.G_TouchTriggers(ent); } return(trace); }
public static int SV_FlyMove(edict_t ent, float time, int mask) { edict_t hit; int bumpcount, numbumps; float[] dir = { 0.0f, 0.0f, 0.0f }; float d; int numplanes; var planes = new float[SV.MAX_CLIP_PLANES][]; float[] primal_velocity = { 0.0f, 0.0f, 0.0f }; float[] original_velocity = { 0.0f, 0.0f, 0.0f }; float[] new_velocity = { 0.0f, 0.0f, 0.0f }; int i, j; trace_t trace; float[] end = { 0.0f, 0.0f, 0.0f }; float time_left; int blocked; for (var n = 0; n < planes.Length; n++) { planes[n] = new float[3]; } numbumps = 4; blocked = 0; Math3D.VectorCopy(ent.velocity, original_velocity); Math3D.VectorCopy(ent.velocity, primal_velocity); numplanes = 0; time_left = time; ent.groundentity = null; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) { end[i] = ent.s.origin[i] + time_left * ent.velocity[i]; } trace = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, end, ent, mask); if (trace.allsolid) { // entity is trapped in another solid Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return(3); } if (trace.fraction > 0) { // actually covered some distance Math3D.VectorCopy(trace.endpos, ent.s.origin); Math3D.VectorCopy(ent.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) { break; // moved the entire distance } hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (hit.solid == Defines.SOLID_BSP) { ent.groundentity = hit; ent.groundentity_linkcount = hit.linkcount; } } if (trace.plane.normal[2] == 0.0f) { blocked |= 2; // step } // // run the impact function // SV.SV_Impact(ent, trace); if (!ent.inuse) { break; // removed by the impact function } time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= SV.MAX_CLIP_PLANES) { // this shouldn't // really happen Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return(3); } Math3D.VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i = 0; i < numplanes; i++) { GameBase.ClipVelocity(original_velocity, planes[i], new_velocity, 1); for (j = 0; j < numplanes; j++) { if (j != i && !Math3D.VectorEquals(planes[i], planes[j])) { if (Math3D.DotProduct(new_velocity, planes[j]) < 0) { break; // not ok } } } if (j == numplanes) { break; } } if (i != numplanes) { // go along this plane Math3D.VectorCopy(new_velocity, ent.velocity); } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == // %i\n",numplanes); Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return(7); } Math3D.CrossProduct(planes[0], planes[1], dir); d = Math3D.DotProduct(dir, ent.velocity); Math3D.VectorScale(dir, d, ent.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Math3D.DotProduct(ent.velocity, primal_velocity) <= 0) { Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return(blocked); } } return(blocked); }