/* ============= SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ static void SV_Physics_Toss(prog.edict_t ent) { world.trace_t trace= new world.trace_t(); double[] move = new double[3] {0, 0, 0}; double backoff; // regular thinking if (!SV_RunThink (ent)) return; // if onground, return without moving if ( ((int)ent.v.flags & FL_ONGROUND) != 0 ) return; SV_CheckVelocity (ent); // add gravity if (ent.v.movetype != MOVETYPE_FLY && ent.v.movetype != MOVETYPE_FLYMISSILE) SV_AddGravity (ent); // move angles mathlib.VectorMA (ent.v.angles, host.host_frametime, ent.v.avelocity, ent.v.angles); // move origin mathlib.VectorScale (ent.v.velocity, host.host_frametime, move); trace = SV_PushEntity (ent, move); if (trace.fraction == 1) return; if (ent.free) return; if (ent.v.movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1; ClipVelocity(ent.v.velocity, trace.plane.normal, ent.v.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { if (ent.v.velocity[2] < 60 || ent.v.movetype != MOVETYPE_BOUNCE) { ent.v.flags = (int)ent.v.flags | FL_ONGROUND; ent.v.groundentity = prog.EDICT_TO_PROG(trace.ent); mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity); mathlib.VectorCopy(mathlib.vec3_origin, ent.v.avelocity); } } // check for in water SV_CheckWaterTransition(ent); }
private static void SV_Physics_Step(prog.edict_t ent) { bool hitsound; // freefall if not onground if (!(((int)ent.v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM)) != 0)) { if (ent.v.velocity[2] < sv_gravity.value * -0.1) hitsound = true; else hitsound = false; SV_AddGravity(ent); SV_CheckVelocity(ent); var unused_trace_t = new world.trace_t(); // null was passed into SV_FlyMove in original SV_FlyMove(ent, host.host_frametime, ref unused_trace_t); world.SV_LinkEdict(ent, true); if (((int)ent.v.flags & FL_ONGROUND) != 0) // just hit ground { if (hitsound) SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1); } } // regular thinking SV_RunThink(ent); SV_CheckWaterTransition(ent); }
/* ================ SV_Physics_Client Player character actions ================ */ static void SV_Physics_Client(prog.edict_t ent, int num) { //Debug.WriteLine("SV_Physics_Client"); if ( ! svs.clients[num-1].active ) return; // unconnected slot // // call standard client pre-think // prog.pr_global_struct[0].time = sv.time; prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent); prog.PR_ExecuteProgram(prog.pr_functions[prog.pr_global_struct[0].PlayerPreThink]); // // do a move // SV_CheckVelocity (ent); // // decide which move function to call // switch ((int)ent.v.movetype) { case MOVETYPE_NONE: if (!SV_RunThink (ent)) return; break; case MOVETYPE_WALK: if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! (((int)ent.v.flags & FL_WATERJUMP) != 0) ) SV_AddGravity (ent); SV_CheckStuck (ent); SV_WalkMove (ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: SV_Physics_Toss (ent); break; case MOVETYPE_FLY: if (!SV_RunThink (ent)) return; var unused_trace_t = new world.trace_t(); // null was passed into SV_FlyMove in original SV_FlyMove(ent, host.host_frametime, ref unused_trace_t); break; case MOVETYPE_NOCLIP: if (!SV_RunThink (ent)) return; mathlib.VectorMA (ent.v.origin, host.host_frametime, ent.v.velocity, ent.v.origin); break; default: sys_linux.Sys_Error ("SV_Physics_client: bad movetype " + (int)ent.v.movetype); break; } // // call standard player post-think // world.SV_LinkEdict (ent, true); prog.pr_global_struct[0].time = sv.time; prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent); prog.PR_ExecuteProgram(prog.pr_functions[prog.pr_global_struct[0].PlayerPostThink]); }
/* ===================== SV_WalkMove Only used by players ====================== */ public static void SV_WalkMove(prog.edict_t ent) { double[] upmove = new double[3] {0, 0, 0}, downmove = new double[3] {0, 0, 0}; double[] oldorg = new double[3] {0, 0, 0}, oldvel = new double[3] {0, 0, 0}; double[] nosteporg = new double[3] {0, 0, 0}, nostepvel = new double[3] {0, 0, 0}; int clip; int oldonground; world.trace_t steptrace = new world.trace_t(), downtrace = new world.trace_t(); // // do a regular slide move unless it looks like you ran into a step // oldonground = (int)ent.v.flags & FL_ONGROUND; ent.v.flags = (int)ent.v.flags & ~FL_ONGROUND; mathlib.VectorCopy(ent.v.origin, oldorg); mathlib.VectorCopy(ent.v.velocity, oldvel); clip = SV_FlyMove(ent, host.host_frametime, ref steptrace); if (!((clip & 2) != 0)) return; // move didn't block on a step if (!(oldonground != 0) && ent.v.waterlevel == 0) return; // don't stair up while jumping if (ent.v.movetype != MOVETYPE_WALK) return; // gibbed by a trigger if (sv_nostep.value != 0.0) return; if (((int)sv_player.v.flags & FL_WATERJUMP) != 0) return; mathlib.VectorCopy(ent.v.origin, nosteporg); mathlib.VectorCopy(ent.v.velocity, nostepvel); // // try moving up and forward to go up a step // mathlib.VectorCopy(oldorg, ent.v.origin); // back to start pos mathlib.VectorCopy(mathlib.vec3_origin, upmove); mathlib.VectorCopy(mathlib.vec3_origin, downmove); upmove[2] = STEPSIZE; downmove[2] = -STEPSIZE + oldvel[2] * host.host_frametime; // move up SV_PushEntity(ent, upmove); // FIXME: don't link? // move forward ent.v.velocity[0] = oldvel[0]; ent.v.velocity[1] = oldvel[1]; ent.v.velocity[2] = 0; clip = SV_FlyMove(ent, host.host_frametime, ref steptrace); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls if (clip != 0) { if ( Math.Abs(oldorg[1] - ent.v.origin[1]) < 0.03125 && Math.Abs(oldorg[0] - ent.v.origin[0]) < 0.03125) { // stepping up didn't make any progress clip = SV_TryUnstick(ent, oldvel); } } // extra friction based on view angle if ((clip & 2) != 0) SV_WallFriction(ent, steptrace); // move down downtrace = SV_PushEntity(ent, downmove); // FIXME: don't link? if (downtrace.plane.normal[2] > 0.7) { if (ent.v.solid == SOLID_BSP) { ent.v.flags = (int)ent.v.flags | FL_ONGROUND; ent.v.groundentity = prog.EDICT_TO_PROG(downtrace.ent); } } else { // if the push down didn't end up on good ground, use the move without // the step up. This happens near wall / slope combinations, and can // cause the player to hop up higher on a slope too steep to climb mathlib.VectorCopy(nosteporg, ent.v.origin); mathlib.VectorCopy(nostepvel, ent.v.velocity); } }
/* ===================== SV_TryUnstick Player has come to a dead stop, possibly due to the problem with limited float precision at some angle joins in the BSP hull. Try fixing by pushing one pixel in each direction. This is a hack, but in the interest of good gameplay... ====================== */ static int SV_TryUnstick(prog.edict_t ent, double[] oldvel) { int i; double[] oldorg = new double[3] {0, 0, 0}; double[] dir = new double[3] {0, 0, 0}; int clip; world.trace_t steptrace = new world.trace_t(); mathlib.VectorCopy (ent.v.origin, oldorg); mathlib.VectorCopy (mathlib.vec3_origin, dir); for (i=0 ; i<8 ; i++) { // try pushing a little in an axial direction switch (i) { case 0: dir[0] = 2; dir[1] = 0; break; case 1: dir[0] = 0; dir[1] = 2; break; case 2: dir[0] = -2; dir[1] = 0; break; case 3: dir[0] = 0; dir[1] = -2; break; case 4: dir[0] = 2; dir[1] = 2; break; case 5: dir[0] = -2; dir[1] = 2; break; case 6: dir[0] = 2; dir[1] = -2; break; case 7: dir[0] = -2; dir[1] = -2; break; } SV_PushEntity (ent, dir); // retry the original move ent.v.velocity[0] = oldvel[0]; ent.v. velocity[1] = oldvel[1]; ent.v. velocity[2] = 0; clip = SV_FlyMove (ent, 0.1f, ref steptrace); if ( Math.Abs(oldorg[1] - ent.v.origin[1]) > 4 || Math.Abs(oldorg[0] - ent.v.origin[0]) > 4 ) { //Con_DPrintf ("unstuck!\n"); return clip; } // go back to the original pos and try again mathlib.VectorCopy (oldorg, ent.v.origin); } mathlib.VectorCopy (mathlib.vec3_origin, ent.v.velocity); return 7; // still not moving }
static void TraceLine(double[] start, double[] end, double[] impact) { world.trace_t trace; trace = new world.trace_t(); world.SV_RecursiveHullCheck(client.cl.worldmodel.hulls[0], 0, 0, 1, start, end, trace); mathlib.VectorCopy(trace.endpos, impact); }