#include "cm_world_sector_private.h"

void SV_SightTraceEntities_r(cmPointTraceWork_t *sightTraceWork,
                  worldSector_t *sector,
                  float startFraction,
                  float endFraction,
                  const vec3_t start,
                  const vec3_t end)
{
    /*
     * Stock's jae branches test ordered >=, so unordered operands follow the
     * negated paths below (0x0805f08d..0x0805f15a).
     */
    if (!(startFraction >= sightTraceWork->bestTrace.fraction) &&
        (sightTraceWork->contentsMask & sector->entityContentsMask) != 0) {
        const int32_t axis = sector->axis;
        const float startDistance = start[axis] - sector->dist;
        const float endDistance = end[axis] - sector->dist;

        if (!(startDistance >= 0.0f) || !(endDistance >= 0.0f)) {
            if (!(0.0f >= startDistance) ||
                !(0.0f >= endDistance)) {
                const float splitFraction =
                    startDistance / (startDistance - endDistance);
                const float middleFraction =
                    startFraction +
                    (endFraction - startFraction) * splitFraction;
                vec3_t middle;
                const int32_t side = startDistance < 0.0f;

                middle[0] = start[0] + (end[0] - start[0]) * splitFraction;
                middle[1] = start[1] + (end[1] - start[1]) * splitFraction;
                middle[2] = start[2] + (end[2] - start[2]) * splitFraction;

                SV_SightTraceEntities_r(sightTraceWork,
                             CM_LoadWorldSector(sector->children[side]),
                             startFraction,
                             middleFraction,
                             start,
                             middle);
                SV_SightTraceEntities_r(sightTraceWork,
                             CM_LoadWorldSector(sector->children[1 - side]),
                             middleFraction,
                             endFraction,
                             middle,
                             end);
            } else {
                SV_SightTraceEntities_r(sightTraceWork,
                             CM_LoadWorldSector(sector->children[1]),
                             startFraction,
                             endFraction,
                             start,
                             end);
            }
        } else {
            SV_SightTraceEntities_r(sightTraceWork,
                         CM_LoadWorldSector(sector->children[0]),
                         startFraction,
                         endFraction,
                         start,
                         end);
        }

        for (svEntity_t *svEntity =
                 CM_LoadEntityLink(sector->entityLinkHead);
             svEntity != NULL;
             svEntity = CM_LoadEntityLink(svEntity->nextInWorldSector)) {
            SV_SightTraceThroughEntity(sightTraceWork, svEntity);
        }
    }
}
