djcev.com

//

Adding airsteps to Ironwail 0.8.1

Posted by Cameron Vanderzanden on in notes. Source file.
Tags: , , .

The Quake game engine does not distinguish between stair steps and walls. If the player runs into a wall (or a step) the movement code will re-try the move with the starting position one stepheight up then move the player one stepheight down to put them back on the floor. Quake 1 as shipped in 1996 only attempts this stepped move if the player is on the ground. This means that if you jump into a set of stairs and hit the vertical part of a step without landing on ground first you lose your momentum.

Later Quake games allow the player to step up even if they're in the air. Some Quake 1 sourceports implement this feature as well, often disabled by default. The feature is called an "airstep" in these engines and is typically enabled by setting the pm_airstep cvar to 1. The Quakespasm lineage of Quake engines (notably: Ironwail) do not, from what I can tell, implement airsteps.

That's an issue for me because I'd like to play the new cool singleplayer Quake mods but I don't want to get stuck on stairs. Fortunately this is easy to fix. Ironwail is used for most of these new mods & it's just a couple lines of code. Here's a quick patch for Ironwail 0.8.1 that adds rudimentary good-enough airsteps:


ironwail-0.8.1-airsteps.patch

diff --exclude Makefile -Nru ironwail-0.8.1-orig/Quake/sv_phys.c ironwail-0.8.1-hacked/Quake/sv_phys.c
--- ironwail-0.8.1-orig/Quake/sv_phys.c 2026-01-01 13:04:04.000000000 -0800
+++ ironwail-0.8.1-hacked/Quake/sv_phys.c   2026-01-20 19:17:37.866332969 -0800
@@ -865,9 +865,6 @@
    if ( !(clip & 2) )
        return;     // move didn't block on a step

-   if (!oldonground && ent->v.waterlevel == 0)
-       return;     // don't stair up while jumping
-
    if (ent->v.movetype != MOVETYPE_WALK)
        return;     // gibbed by a trigger

@@ -888,7 +885,6 @@
    VectorCopy (vec3_origin, upmove);
    VectorCopy (vec3_origin, downmove);
    upmove[2] = STEPSIZE;
-   downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;

 // move up
    SV_PushEntity (ent, upmove);    // FIXME: don't link?
@@ -914,16 +910,26 @@
    if ( clip & 2 )
        SV_WallFriction (ent, &steptrace);

+   downmove[2] -= ent->v.origin[2] - oldorg[2];
+
 // move down
    downtrace = SV_PushEntity (ent, downmove);  // FIXME: don't link?

-   if (downtrace.plane.normal[2] > 0.7)
+   if (downtrace.allsolid)
+   {
+       VectorCopy (nosteporg, ent->v.origin);
+       VectorCopy (nostepvel, ent->v.velocity);
+   }
+   else 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 = EDICT_TO_PROG(downtrace.ent);
        }
+
+       if (oldvel[2] > 0)
+           ent->v.velocity[2] = oldvel[2];
    }
    else
    {

Responses

If you've written a response to this post then please let me know the URL:

You can also submit a "comment" webmention by pressing the button below. It may take a day or two for your comment to appear here and a copy of your comment will be stored at commentpara.de.