A_CheckSolidFooting

From ZDoom Wiki
Jump to navigation Jump to search

state A_CheckSolidFooting (int offset, int flags = CSF_ALL)
state A_CheckSolidFooting (str "state", int flags = CSF_ALL)

Note: Jump functions perform differently inside of anonymous functions.

This is an example of a custom function that jumps if the calling actor is standing on the ground, an actor or a 3D floor. It is a much more effective and accurate version of A_CheckFloor.

Implementing into your mod

Add the following enum to your project:

enum ECheckSolidFootingFlags
{
    CSF_SOLIDGROUND = 1,
    CSF_SOLIDACTORS = 2,
    
    CSF_ALL = CSF_SOLIDGROUND|CSF_SOLIDACTORS,
}

Then add the following ZScript function to your actor of choice. This does not need to be repeated for classes which inherit from another already possessing this function. Note that the additional oldVelZ variable, and the change to the Tick method are optional. However, you will need to remove the code that makes use of these changes in the A_CheckSolidFooting function if you do not include them.

// add this variable to your actor
double oldVelZ;

override void Tick()
{
    // add the following line to your actor's Tick() method
    oldVelZ = vel.z;
    
    super.Tick();
}

action state A_CheckSolidFooting(StateLabel label, int flags = CSF_ALL)
{
    // small optimization: if our z-vel has changed, we aren't standing on something
    if (invoker.oldVelZ != vel.z)
        return null;
    
    // are we standing on solid ground?
    if (abs(pos.z - GetZAt()) <= 1)
    {
        if (flags & CSF_SOLIDGROUND)
            return ResolveState(label);
    }
    
    // are we standing on an actor?
    bool ok; Actor below;
    [ok, below] = TestMobjZ(true);
    if (below)
    {
        if (flags & CSF_SOLIDACTORS)
            return ResolveState(label);
    }
    
    // has our z-velocity not changed?
    if (vel.z == invoker.oldVelZ && (flags & CSF_SOLIDGROUND))
        return ResolveState(label);
    
    // we aren't standing on anything
    return null;
}

The function is now ready for use.

Examples

The following example will force the actor into the first frame of its Death state when on the ground, and the first frame of its Spawn state when in the air.

override void Tick()
{
    let r = A_CheckSolidFooting("Death");
    if (r == null)
        SetStateLabel("Spawn");
    else
        SetState(r);

    oldVelZ = vel.z;
    super.Tick();
}

See also