]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/portals.c
quake3/help: move away from termcap
[xonotic/netradiant.git] / tools / quake3 / q3map2 / portals.c
index ff1e9845bf36b703a29891db160bc923dfa921e3..27ae8c31f31d8705d0eb06109ba3323386c69b6d 100644 (file)
@@ -62,8 +62,7 @@ portal_t *AllocPortal( void ){
                c_peak_portals = c_active_portals;
        }
 
-       p = safe_malloc( sizeof( portal_t ) );
-       memset( p, 0, sizeof( portal_t ) );
+       p = safe_malloc0( sizeof( portal_t ) );
 
        return p;
 }
@@ -409,6 +408,7 @@ void SplitNodePortals( node_t *node ){
 //
 // cut the portal into two portals, one on each side of the cut plane
 //
+               /* not strict, we want to always keep one of them even if coplanar */
                ClipWindingEpsilon( p->winding, plane->normal, plane->dist,
                                                        SPLIT_WINDING_EPSILON, &frontwinding, &backwinding );
 
@@ -519,7 +519,7 @@ void MakeTreePortals_r( node_t *node ){
 
        CalcNodeBounds( node );
        if ( node->mins[0] >= node->maxs[0] ) {
-               Sys_Printf( "WARNING: node without a volume\n" );
+               Sys_FPrintf( SYS_WRN, "WARNING: node without a volume\n" );
                Sys_Printf( "node has %d tiny portals\n", node->tinyportals );
                Sys_Printf( "node reference point %1.2f %1.2f %1.2f\n", node->referencepoint[0],
                                        node->referencepoint[1],
@@ -585,7 +585,22 @@ void FloodPortals_r( node_t *node, int dist, qboolean skybox ){
                node->skybox = skybox;
        }
 
-       if ( node->occupied || node->opaque ) {
+       if ( node->opaque ) {
+               return;
+       }
+
+       if ( node->occupied ) {
+               if ( node->occupied > dist ) {
+                       /* reduce distance! */
+                       /* for better leak line */
+                       /* note: node->occupied will also be true for all further nodes, then */
+                       node->occupied = dist;
+                       for ( p = node->portals; p; p = p->next[ s ] )
+                       {
+                               s = ( p->nodes[ 1 ] == node );
+                               FloodPortals_r( p->nodes[ !s ], dist + 1, skybox );
+                       }
+               }
                return;
        }
 
@@ -646,13 +661,14 @@ qboolean PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, qbo
    =============
  */
 
-qboolean FloodEntities( tree_t *tree ){
+int FloodEntities( tree_t *tree ){
        int i, s;
        vec3_t origin, offset, scale, angles;
-       qboolean r, inside, tripped, skybox;
+       qboolean r, inside, skybox, found;
        node_t      *headnode;
-       entity_t    *e;
+       entity_t    *e, *tripped;
        const char  *value;
+       int tripcount;
 
 
        headnode = tree->headnode;
@@ -668,8 +684,15 @@ qboolean FloodEntities( tree_t *tree ){
                e = &entities[ i ];
 
                /* get origin */
-               GetVectorForKey( e, "origin", origin );
-               if ( VectorCompare( origin, vec3_origin ) ) {
+               found = GetVectorForKey( e, "origin", origin );
+
+               /* as a special case, allow origin-less entities */
+               if ( !found ) {
+                       continue;
+               }
+
+               /* also allow bmodel entities outside, as they could be on a moving path that will go into the map */
+               if ( e->brushes != NULL || e->patches != NULL ) {
                        continue;
                }
 
@@ -721,22 +744,33 @@ qboolean FloodEntities( tree_t *tree ){
                if ( r ) {
                        inside = qtrue;
                }
-               if ( ( !r || tree->outside_node.occupied ) && !tripped ) {
-                       xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
-                       tripped = qtrue;
+               if ( !r ) {
+                       Sys_Printf( "Entity %i, Brush %i: Entity in solid\n", e->mapEntityNum, 0 );
                }
+               else if ( tree->outside_node.occupied ) {
+                       if ( !tripped || tree->outside_node.occupied < tripcount ) {
+                               tripped = e;
+                               tripcount = tree->outside_node.occupied;
+                       }
+               }
+       }
+
+       if ( tripped ) {
+               xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
        }
 
        Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );
 
        if ( !inside ) {
                Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
+               return FLOODENTITIES_EMPTY;
        }
-       else if ( tree->outside_node.occupied ) {
-               Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );
+       if ( tree->outside_node.occupied ) {
+               Sys_FPrintf( SYS_VRB, "entity reached from outside -- leak detected\n" );
+               return FLOODENTITIES_LEAKED;
        }
 
-       return (qboolean) ( inside && !tree->outside_node.occupied );
+       return FLOODENTITIES_GOOD;
 }
 
 /*
@@ -777,7 +811,7 @@ void FloodAreas_r( node_t *node ){
 
                // note the current area as bounding the portal
                if ( b->portalareas[ 1 ] != -1 ) {
-                       Sys_Printf( "WARNING: areaportal brush %i touches > 2 areas\n", b->brushNum );
+                       Sys_FPrintf( SYS_WRN, "WARNING: areaportal brush %i touches > 2 areas\n", b->brushNum );
                        return;
                }
                if ( b->portalareas[ 0 ] != -1 ) {
@@ -864,7 +898,7 @@ void CheckAreas_r( node_t *node ){
 
        if ( node->cluster != -1 ) {
                if ( node->area == -1 ) {
-                       Sys_Printf( "WARNING: cluster %d has area set to -1\n", node->cluster );
+                       Sys_FPrintf( SYS_WRN, "WARNING: cluster %d has area set to -1\n", node->cluster );
                }
        }
        if ( node->areaportal ) {
@@ -872,7 +906,7 @@ void CheckAreas_r( node_t *node ){
 
                // check if the areaportal touches two areas
                if ( b->portalareas[0] == -1 || b->portalareas[1] == -1 ) {
-                       Sys_Printf( "WARNING: areaportal brush %i doesn't touch two areas\n", b->brushNum );
+                       Sys_FPrintf( SYS_WRN, "WARNING: areaportal brush %i doesn't touch two areas\n", b->brushNum );
                }
        }
 }