/// <summary> /// Check if the player can jump. /// </summary> private static void PM_CheckJump() { if (InputContainer.upMove <= 0) { pmflags &= ~PMFlags.PMF_JUMP_HELD; return; } if (pmflags.HasFlag(PMFlags.PMF_JUMP_HELD)) { return; } //swimming if (waterlevel >= 2) { groundentity = false; if (velocity.y <= -300) { return; } //FIXME: John wanted to fix this so... if (watertype == BrushContents.CONTENTS_WATER) { velocity.y = 100; } else if (watertype == BrushContents.CONTENTS_SLIME) { velocity.y = 80; } else { velocity.y = 50; } return; } //in air? if (!groundentity) { return; } pmflags |= PMFlags.PMF_JUMP_HELD; groundentity = false; pmflags &= ~PMFlags.PMF_ON_GROUND; velocity.y += 270; if (velocity.y < 270) { velocity.y = 270; } //play sound pmd.jumped = true; }
/// <summary> /// Check if climbing a ladder or jumping out of water. /// </summary> private static void PM_CheckSpecialMovement() { Vector3 spot; BrushContents cont; Vector3 flatforward; TraceT trace; if (timer > 0) { return; } ladder = false; //check for ladder flatforward = pmd.inForward; flatforward.y = 0; flatforward.Normalize(); spot = origin + flatforward * 1; trace = Trace.CL_Trace(origin, mins, maxs, spot); if ((trace.fraction < 1) && trace.contents.HasFlag(BrushContents.CONTENTS_LADDER)) { ladder = true; } //check for waterjump if (waterlevel != 2) { return; } spot = origin + flatforward * 30; spot.y += 4; cont = Utils.NodePointSearch(BSPFile.headnode, spot).contents; if (!cont.HasFlag(BrushContents.CONTENTS_SOLID)) { return; } spot.y += 16; cont = Utils.NodePointSearch(BSPFile.headnode, spot).contents; if (cont != 0) { return; } //jump out of water velocity = flatforward * 50; velocity.y = 350; pmflags |= PMFlags.PMF_TIME_WATERJUMP; timer = 0.255f; }
/// <summary> /// Sets player extents and viewheight. /// </summary> private static void PM_CheckDuck() { mins.x = -16; mins.z = -16; maxs.x = 16; maxs.z = 16; mins.y = -24; if (InputContainer.upMove < 0 && pmflags.HasFlag(PMFlags.PMF_ON_GROUND)) { pmflags |= PMFlags.PMF_DUCKED; pmd.beginCameraLerp = true; } else { //stand up if possible if (pmflags.HasFlag(PMFlags.PMF_DUCKED)) { //try to stand up maxs.y = 32; TraceT trace = Trace.CL_Trace(origin, mins, maxs, origin); if (!trace.allsolid) { pmflags &= ~PMFlags.PMF_DUCKED; } } } if (pmflags.HasFlag(PMFlags.PMF_DUCKED)) { maxs.y = 4; viewheight = -2; } else { maxs.y = 32; viewheight = 22; } }
/// <summary> /// Checks if player is standing on the ground and if he is in a water body. /// </summary> private static void PM_CategorizePosition() { TraceT trace; BrushContents cont; int sample1, sample2; if (velocity.y > 180) { groundentity = false; pmflags &= ~PMFlags.PMF_ON_GROUND; } else { trace = Trace.CL_Trace(origin, mins, maxs, origin - new Vector3(0, 0.25f, 0)); groundplane = trace.plane; groundsurface = trace.surface; groundcontents = trace.contents; if (trace.plane == null || (trace.plane.normal.y < 0.7f && !trace.startsolid)) { groundentity = false; pmflags &= ~PMFlags.PMF_ON_GROUND; } else { groundentity = true; //hitting solid ground will end a waterjump if (pmflags.HasFlag(PMFlags.PMF_TIME_WATERJUMP)) { pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } if (!pmflags.HasFlag(PMFlags.PMF_ON_GROUND)) { //just hit the ground pmflags |= PMFlags.PMF_ON_GROUND; } } } //get waterlevel waterlevel = 0; watertype = 0; sample2 = (int)viewheight - (int)mins.y; sample1 = sample2 / 2; Vector3 point = origin; point.y = origin.y + mins.y + 1; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { watertype = cont; waterlevel = 1; point.y = origin.y + mins.y + sample1; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { waterlevel = 2; point.y = origin.y + mins.y + sample2; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { waterlevel = 3; } } } }
public static void Pmove(ref PlayerMoveData pmd) { //default mins = Vector3.zero; maxs = Vector3.zero; PlayerMove.pmd = pmd; groundplane = null; origin = pmd.inOrigin * 0.125f; velocity = pmd.inVelocity * 0.125f; frametime = pmd.frametime; pmflags = pmd.flags; if (pmd.addVelocities != Vector3.zero) { velocity += pmd.addVelocities; } if (PlayerState.mode == GameMode.flying) { PM_FlyMove(); if (PlayerState.Noclip) { origin += velocity * frametime; } else { PM_StepSlideMove_(); } FinishPmove(); pmd = PlayerMove.pmd; return; } PM_CheckDuck(); if (pmd.initialSnap) { PM_InitialSnapPosition(); } PM_CategorizePosition(); PM_CheckSpecialMovement(); //drop timing counter if (timer > 0) { float msec = frametime; if (msec == 0) { //? msec = 1; } if (msec >= timer) { pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } else { timer -= msec; } } if (pmflags.HasFlag(PMFlags.PMF_TIME_WATERJUMP)) { velocity.y -= PlayerState.pm_gravity * frametime; if (velocity.y < 0) { //cancel waterjump when we start falling pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } PM_StepSlideMove(); } else { PM_CheckJump(); PM_Friction(); if (waterlevel >= 2) { PM_WaterMove(); } else { PM_AirMove(); } } PM_CategorizePosition(); FinishPmove(); pmd = PlayerMove.pmd; }
private void Update() { //check if a map is loaded if (Cvar.Integer("maploaded") == 0) { return; } //mouse movement MouseLook(); PlayerMoveData pmd; if (Globals.async.Boolean) { elapsedAsyncFrametime += Time.deltaTime; pmd = new PlayerMoveData { inOrigin = lastAsyncOrigin, inVelocity = lastAsyncVelocity, inForward = Camera.transform.forward, inRight = Camera.transform.right, camX = camX, camY = camY, addVelocities = PlayerState.addVelocities, gravity = PlayerState.pm_gravity, frametime = elapsedAsyncFrametime, //run delta time from last async frame initialSnap = snapRequired, flags = pmflags }; } else { pmd = new PlayerMoveData { inOrigin = out_origin, inVelocity = out_velocity, inForward = Camera.transform.forward, inRight = Camera.transform.right, camX = camX, camY = camY, addVelocities = PlayerState.addVelocities, gravity = PlayerState.pm_gravity, frametime = Time.deltaTime, //run current delta time initialSnap = snapRequired, flags = pmflags }; } //queue velocities for async lastAsyncAddVelocity += PlayerState.addVelocities; PlayerState.addVelocities = Vector3.zero; //get pmove PlayerMove.Pmove(ref pmd); //play jump sound if (pmd.jumped) { jumpSoundSource.Play(); } //snapped -> position changed by entity. Don't allow going back. if (snapRequired) { previous_origin = pmd.outOrigin; snapRequired = false; } //set data origin = pmd.outOrigin * 0.125f; velocity = pmd.outVelocity * 0.125f; pmflags = pmd.flags; viewheight = pmd.viewheight; //update camera ApplyPmoveToCamera(); //update player state info PlayerState.currentSpeed = new Vector2(velocity.x, velocity.z).magnitude; PlayerState.currentVieweight = viewheight; PlayerState.currentOrigin = origin; PlayerState.mins = pmd.mins; PlayerState.maxs = pmd.maxs; //snap position and store old origin out_origin = origin * 8; out_velocity = pmd.outVelocity; //FIXME: do this only on async switch if (!Globals.async.Boolean) { lastAsyncAddVelocity = Vector3.zero; lastAsyncOrigin = out_origin; lastAsyncVelocity = out_velocity; asyncFlags = pmflags; } }
private void FixedUpdate() { //check if a map is loaded and async is on if (Cvar.Integer("maploaded") == 0 || !Globals.async.Boolean) { return; } PlayerMoveData pmd = new PlayerMoveData { inOrigin = lastAsyncOrigin, inVelocity = lastAsyncVelocity, inForward = Camera.transform.forward, inRight = Camera.transform.right, camX = camX, camY = camY, addVelocities = lastAsyncAddVelocity, gravity = PlayerState.pm_gravity, frametime = Time.fixedDeltaTime, initialSnap = asyncSnapRequired, flags = asyncFlags }; //run async frame PlayerMove.Pmove(ref pmd); //snap doesn't allow going back if (asyncSnapRequired) { previous_origin = pmd.outOrigin; asyncSnapRequired = false; } lastAsyncOrigin = pmd.outOrigin; lastAsyncVelocity = pmd.outVelocity; lastAsyncAddVelocity = Vector3.zero; asyncFlags = pmd.flags; //start counting simulated time again elapsedAsyncFrametime = 0; //overwrite all sync variables with async frame. If everything is done correctly the values should be matching origin = pmd.outOrigin * 0.125f; out_origin = pmd.outOrigin; out_velocity = pmd.outVelocity; velocity = pmd.outVelocity * 0.125f; pmflags = pmd.flags; viewheight = pmd.viewheight; //TODO: is everything below this even needed? ApplyPmoveToCamera(); PlayerState.currentSpeed = new Vector2(velocity.x, velocity.z).magnitude; PlayerState.currentVieweight = viewheight; PlayerState.currentOrigin = origin; PlayerState.mins = pmd.mins; PlayerState.maxs = pmd.maxs; }