Esempio n. 1
0
static int FindGoalAASArea(edict_t *ent)
{
    AiAasWorld *aasWorld = AiAasWorld::Instance();
    if (!aasWorld->IsLoaded())
        return 0;

    Vec3 mins(ent->r.mins), maxs(ent->r.maxs);
    // Extend AABB XY dimensions
    ExtendDimension(mins.Data(), maxs.Data(), 0);
    ExtendDimension(mins.Data(), maxs.Data(), 1);
    // Z needs special extension rules
    float presentHeight = maxs.Z() - mins.Z();
    float playerHeight = playerbox_stand_maxs[2] - playerbox_stand_mins[2];
    if (playerHeight > presentHeight)
        maxs.Z() += playerHeight - presentHeight;


    // Find all areas in bounds
    int areas[16];
    // Convert bounds to absolute ones
    mins += ent->s.origin;
    maxs += ent->s.origin;
    const int numAreas = aasWorld->BBoxAreas(mins, maxs, areas, 16);

    // Find hub areas (or use cached)
    FindHubAreas();

    int bestArea = 0;
    int bestAreaReachCount = 0;
    AiAasRouteCache *routeCache = AiAasRouteCache::Shared();
    for (int i = 0; i < numAreas; ++i)
    {
        const int areaNum = areas[i];
        int areaReachCount = 0;
        for (const int hubAreaNum: hubAreas)
        {
            const aas_area_t &hubArea = aasWorld->Areas()[hubAreaNum];
            Vec3 hubAreaPoint(hubArea.center);
            hubAreaPoint.Z() = hubArea.mins[2] + std::min(24.0f, hubArea.maxs[2] - hubArea.mins[2]);
            // Do not waste pathfinder cycles testing for preferred flags that may fail.
            constexpr int travelFlags = Bot::ALLOWED_TRAVEL_FLAGS;
            if (routeCache->ReachabilityToGoalArea(hubAreaNum, hubAreaPoint.Data(), areaNum, travelFlags))
            {
                areaReachCount++;
                // Thats't enough, do not waste CPU cycles
                if (areaReachCount == 4)
                    return areaNum;
            }
        }
        if (areaReachCount > bestAreaReachCount)
        {
            bestArea = areaNum;
            bestAreaReachCount = areaReachCount;
        }
    }
    if (bestArea)
        return bestArea;

    // Fall back to a default method and hope it succeeds
    return aasWorld->FindAreaNum(ent);
}