diff --git a/code/game/bg_local.h b/code/game/bg_local.h index 223c688..0b67651 100644 --- a/code/game/bg_local.h +++ b/code/game/bg_local.h @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define STEPSIZE 18 -#define JUMP_VELOCITY 270 +#define JUMP_VELOCITY 275 #define TIMER_LAND 130 #define TIMER_GESTURE (34*66+50) @@ -77,6 +77,8 @@ void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ); void PM_AddTouchEnt( int entityNum ); void PM_AddEvent( int newEvent ); +qboolean PM_CanJump( void ); +void PM_Jump( void ); qboolean PM_SlideMove( qboolean gravity ); void PM_StepSlideMove( qboolean gravity ); diff --git a/code/game/bg_pmove.c b/code/game/bg_pmove.c index 3711869..9d1a188 100644 --- a/code/game/bg_pmove.c +++ b/code/game/bg_pmove.c @@ -353,32 +353,55 @@ static void PM_SetMovementDir( void ) { /* ============= -PM_CheckJump +PM_Jump + +Applies jump velocity, event, and animation. +Extracted from PM_CheckJump so it can be called +from other contexts (step jump, double jump, etc). ============= */ -static qboolean PM_CheckJump( void ) { +/* +============= +PM_CanJump + +Returns qtrue if a jump would succeed right now. +Checks both player state AND input (upmove >= 10). +Used by PM_StepSlideMove to decide whether stepping +up stairs should trigger a jump. +============= +*/ +qboolean PM_CanJump( void ) { if ( pm->ps->pm_flags & PMF_RESPAWNED ) { - return qfalse; // don't allow jump until all buttons are up + return qfalse; + } + + if ( pm->ps->pm_type != PM_NORMAL ) { + return qfalse; } if ( pm->cmd.upmove < 10 ) { - // not holding jump return qfalse; } - // must wait for jump to be released - if ( pm->ps->pm_flags & PMF_JUMP_HELD ) { - // clear upmove so cmdscale doesn't lower running speed - pm->cmd.upmove = 0; + // QL: 100ms minimum delay between jumps. + // Prevents same-frame double-fires. Step jumps launch the player + // high enough (~400ms airtime) that the next stair collision + // naturally exceeds this threshold. + if ( pm->cmd.serverTime - pm->ps->lastJumpTime < 100 ) { return qfalse; } + return qtrue; +} + +void PM_Jump( void ) { pml.groundPlane = qfalse; // jumping away pml.walking = qfalse; pm->ps->pm_flags |= PMF_JUMP_HELD; pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->velocity[2] = JUMP_VELOCITY; + pm->ps->lastJumpTime = pm->cmd.serverTime; PM_AddEvent( EV_JUMP ); if ( pm->cmd.forwardmove >= 0 ) { @@ -388,6 +411,23 @@ static qboolean PM_CheckJump( void ) { PM_ForceLegsAnim( LEGS_JUMPB ); pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; } +} + +/* +============= +PM_CheckJump +============= +*/ +static qboolean PM_CheckJump( void ) { + if ( !PM_CanJump() ) { + return qfalse; + } + + // QL autohop: no PMF_JUMP_HELD gate here. + // The Pmove() outer loop forces upmove=20 when + // PMF_JUMP_HELD is set, allowing continuous bunny hopping. + + PM_Jump(); return qtrue; } diff --git a/code/game/bg_slidemove.c b/code/game/bg_slidemove.c index ed1349f..6c7b307 100644 --- a/code/game/bg_slidemove.c +++ b/code/game/bg_slidemove.c @@ -246,15 +246,9 @@ void PM_StepSlideMove( qboolean gravity ) { return; // we got exactly where we wanted to go first try } - VectorCopy(start_o, down); - down[2] -= STEPSIZE; - pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); - VectorSet(up, 0, 0, 1); - // never step up when you still have up velocity - if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || - DotProduct(trace.plane.normal, up) < 0.7)) { - return; - } + // QL pm_airSteps: allow step-ups with upward velocity. + // Q3 blocked step-ups during jumps unless ground was directly below. + // This prevented smooth stair traversal while bunny-hopping. VectorCopy (pm->ps->origin, down_o); VectorCopy (pm->ps->velocity, down_v); @@ -285,8 +279,14 @@ void PM_StepSlideMove( qboolean gravity ) { if ( !trace.allsolid ) { VectorCopy (trace.endpos, pm->ps->origin); } + // QL: only clip velocity to step surface when moving INTO it. + // Skip clip when velocity is already moving away (preserves + // upward momentum through stair steps during bunny-hopping). if ( trace.fraction < 1.0 ) { - PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); + float vdotn = DotProduct( pm->ps->velocity, trace.plane.normal ); + if ( vdotn < 0 || fabs( vdotn ) < 0.001f ) { + PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP ); + } } #if 0 diff --git a/code/game/q_shared.h b/code/game/q_shared.h index eed5689..99e5a67 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1212,6 +1212,9 @@ typedef struct playerState_s { int pmove_framecount; // FIXME: don't transmit over the network int jumppad_frame; int entityEventSequence; + + // QL additions + int lastJumpTime; // serverTime of last jump, for 100ms cooldown } playerState_t; diff --git a/code/qcommon/msg.c b/code/qcommon/msg.c index 27891cc..97110f8 100644 --- a/code/qcommon/msg.c +++ b/code/qcommon/msg.c @@ -1147,7 +1147,8 @@ netField_t playerStateFields[] = { PSF(grapplePoint[1]), 0 }, { PSF(grapplePoint[2]), 0 }, { PSF(jumppad_ent), 10 }, -{ PSF(loopSound), 16 } +{ PSF(loopSound), 16 }, +{ PSF(lastJumpTime), 32 } }; /*