Obtaining colliding ladder reference Created 2 years ago2022-10-10 16:41:47 UTC by Neoptolemus Neoptolemus

Created 2 years ago2022-10-10 16:41:47 UTC by Neoptolemus Neoptolemus

Posted 2 years ago2022-10-10 16:41:47 UTC Post #346961
Hi all,

I'm wondering if it's possible when a player is on a ladder to obtain a reference to the func_ladder they're claiming on or, ideally, the surface normal they're climbing on?

The reason for this is I'm writing a bot to play some HL1 mods, and for ladder climbing it would be useful to tell the bot which direction to move in order to ascend/descend the ladder without relying on external hints like waypoints.

I've tried using traces, but I don't believe func_ladders collide so it just returns worldspawn, unless I'm missing a flag to allow func_ladders to block the trace.

Thanks!
Posted 2 years ago2022-10-12 14:07:05 UTC Post #346966
Ok, I have come up with an initial implementation using a mix of techniques:

1. Loop through all func_ladder entities using UTIL_FindEntityByClassname
2. Define a line going from the ladder entity's bounding box min and max (pev->absmin, pev->absmax)
3. Calculate the distance of the player's origin from that line (code for this below) and pick whichever ladder produces the lowest distance
4. Find the midpoint between the ladder's bounding box min and max, and then use UTIL_TRACEHULL from the player's origin to that midpoint to get the impact normal, which will be your ladder's surface normal. We use TRACEHULL rather than TRACELINE in case the ladder is a func_illusionary

There would be an issue with very fat ladder brushes since the distance from that line would be quite high, but these are generally very rare and it's unlikely to have a really fat ladder brush close to a thin ladder brush, so probably not an edge case worth investigating.
Vector UTIL_ClosestPointOnLine(Vector lineFrom, Vector lineTo, Vector point) {

        Vector vVector1 = point - lineFrom;
        Vector vVector2 = (lineTo - lineFrom);
        UTIL_NormalizeVector(&vVector2);

        float d = vDist3D(lineFrom, lineTo);
        float t = UTIL_GetDotProduct(vVector2, vVector1);

        if (t <= 0)
            return lineFrom;

        if (t >= d)
            return lineTo;

        Vector vVector3 = vVector2 * t;

        Vector vClosestPoint = lineFrom + vVector3;

        return vClosestPoint;
}

float UTIL_DistanceFromLine3D(Vector lineFrom, Vector lineTo, Vector point) {
    Vector nearestToLine = UTIL_ClosestPointOnLine(lineFrom, lineTo, point);
    return vDist3D(point, nearestToLine);
}
Posted 2 years ago2022-10-14 20:14:14 UTC Post #346969
Seems like a good enough approximation.
Admer456 Admer456If it ain't broken, don't fox it!
You must be logged in to post a response.