From c53f39601df46e5ac74c6812e64c6418d09a0f9d Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Thu, 30 Apr 2026 15:21:28 +0100 Subject: [PATCH] feat(gameengine): floaty low-grav jumps for fun-feel q3 movement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace held-jump-extends-height (Mario-style) with a Q3-style impulse jump: set vel.y once on press, gravity does the rest. Apply per-player gravity scaling symmetrically in air (rising and falling) so jumps don't feel floaty going up but heavy coming down. Tune q3_frame for a fun, floaty feel rather than authentic Q3 numbers: gravity_scale 0.55 (≈55% Earth) + jump_velocity 5.5 → ~2.8m apex, ~2s airtime. Trades rocket-dodge utility for hang-time enjoyment. Co-Authored-By: Claude Opus 4.6 --- .../packages/quake3/workflows/q3_frame.json | 7 ++- .../workflow_physics_fps_move_step.cpp | 46 ++++++------------- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/gameengine/packages/quake3/workflows/q3_frame.json b/gameengine/packages/quake3/workflows/q3_frame.json index 41bd2e264..e3311e674 100644 --- a/gameengine/packages/quake3/workflows/q3_frame.json +++ b/gameengine/packages/quake3/workflows/q3_frame.json @@ -17,10 +17,9 @@ "move_speed": 4.5, "sprint_multiplier": 1.5, "crouch_multiplier": 0.45, - "jump_height": 0.9, - "jump_duration": 0.22, - "air_control": 0.15, - "gravity_scale": 1.6, + "jump_velocity": 5.5, + "air_control": 0.25, + "gravity_scale": 0.55, "ground_accel": 30.0, "ground_friction": 24.0, "crouch_height": 0.5, diff --git a/gameengine/src/services/impl/workflow/workflow_generic_steps/workflow_physics_fps_move_step.cpp b/gameengine/src/services/impl/workflow/workflow_generic_steps/workflow_physics_fps_move_step.cpp index 0d2e71fb7..7d85ce814 100644 --- a/gameengine/src/services/impl/workflow/workflow_generic_steps/workflow_physics_fps_move_step.cpp +++ b/gameengine/src/services/impl/workflow/workflow_generic_steps/workflow_physics_fps_move_step.cpp @@ -37,7 +37,6 @@ void WorkflowPhysicsFpsMoveStep::Execute( const float moveSpeed = getNum("move_speed", 6.0f); const float sprintMultiplier = getNum("sprint_multiplier", 1.8f); const float crouchMultiplier = getNum("crouch_multiplier", 0.4f); - const float jumpForce = getNum("jump_force", 5.0f); const float crouchHeight = getNum("crouch_height", 0.8f); const float standHeight = getNum("stand_height", 1.6f); const float airControl = getNum("air_control", 0.3f); @@ -138,43 +137,28 @@ void WorkflowPhysicsFpsMoveStep::Execute( float newX = curX + (moveX - curX) * airControl; float newZ = curZ + (moveZ - curZ) * airControl; body->setLinearVelocity(btVector3(newX, currentVel.y(), newZ)); - - // Extra downward gravity for snappy Quake-style landing - if (currentVel.y() < 0.0f) { - body->applyCentralForce(btVector3(0, -9.81f * body->getMass() * (gravityScale - 1.0f), 0)); - } } - // Jump - hold space for higher jump, release early for short hop + // Per-player gravity scaling (applies symmetrically in air, both rising + // and falling). gravityScale > 1.0 = heavier; < 1.0 = floatier; 1.0 = + // Earth. Implemented as an additive force on top of the world's -9.81 + // so the rest of the world keeps Earth gravity untouched. + if (!grounded && gravityScale != 1.0f) { + body->applyCentralForce(btVector3(0, -9.81f * body->getMass() * (gravityScale - 1.0f), 0)); + } + + // Quake-style impulse jump: set upward velocity once on press while + // grounded; height is determined by gravity from there. No hold-to-extend. + // The latching `player_jumping` flag prevents auto-bunnyhop from a held key. + const float jumpVelocity = getNum("jump_velocity", 6.5f); bool wasJumping = context.GetBool("player_jumping", false); - float jumpTime = context.Get("player_jump_time", 0.0f); - float jumpDuration = getNum("jump_duration", 1.2f); - float jumpHeight = getNum("jump_height", 3.5f); if (keySpace && !keyCtrl && grounded && !wasJumping) { + btVector3 vel = body->getLinearVelocity(); + body->setLinearVelocity(btVector3(vel.x(), jumpVelocity, vel.z())); context.Set("player_jumping", true); - context.Set("player_jump_time", 0.0f); - jumpTime = 0.0f; } - - if (context.GetBool("player_jumping", false)) { - float dt = 1.0f / 60.0f; - jumpTime += dt; - context.Set("player_jump_time", jumpTime); - - // Keep rising while space is held and under max duration - if (keySpace && jumpTime < jumpDuration) { - float t = jumpTime / jumpDuration; - float upSpeed = (jumpHeight / jumpDuration) * (1.0f - t * t); - btVector3 vel = body->getLinearVelocity(); - body->setLinearVelocity(btVector3(vel.x(), upSpeed, vel.z())); - } else { - // Released space or hit max duration - start falling - context.Set("player_jumping", false); - } - } - - if (grounded && !keySpace) { + if (!keySpace && grounded) { context.Set("player_jumping", false); }