Index: qbsp.h =================================================================== --- qbsp.h (revision 15549) +++ qbsp.h (working copy) @@ -259,7 +259,7 @@ /* routing.c */ -void DoRouting(void); +void DoRouting(const char *filename); /* qbsp3.c */ Index: qbsp3.c =================================================================== --- qbsp3.c (revision 15549) +++ qbsp3.c (working copy) @@ -31,7 +31,7 @@ /** * @sa ProcessModels */ -static void ProcessWorldModel (void) +static void ProcessWorldModel (const char *filename) { entity_t *e; @@ -47,7 +47,7 @@ U2M_ProgressBar(ProcessLevel, NUMMODELS, qtrue, "LEVEL"); /* calculate routing */ - DoRouting(); + DoRouting(filename); } @@ -102,7 +102,7 @@ Sys_FPrintf(SYS_VRB, "############### model %i ###############\n", nummodels); if (entity_num == 0) - ProcessWorldModel(); + ProcessWorldModel(filename); else ProcessSubModel(entity_num); Index: routing.c =================================================================== --- routing.c (revision 15549) +++ routing.c (working copy) @@ -122,7 +122,7 @@ else filled[y][x] |= 1 << z; /* don't enter */ } else { -/* Com_Printf("."); */ +/* fprintf(handle, "."); */ /* elevated a lot */ end[2] = start[2]; start[2] += UNIT_HEIGHT - PLAYER_HEIGHT; @@ -146,7 +146,7 @@ end[2] = start[2] + PLAYER_HEIGHT - (start[2]-tr_end[2]); height = UNIT_HEIGHT - (start[2]-tr_end[2]); -/* Com_Printf("%i %i\n", (int)height, (int)(start[2]-tr_end[2])); */ +/* fprintf(handle, "%i %i\n", (int)height, (int)(start[2]-tr_end[2])); */ if (!TestLineDM(start, end, tr_end, 2)) route[z][y][x] = ((height + QUANT / 2) / QUANT < 0) ? 0 : (height + QUANT / 2) / QUANT; @@ -169,13 +169,19 @@ { int x, y, z, sz, ax, ay; int i, h, sh; + int hc; /* height check */ + qboolean vacant; pos3_t pos; vec3_t start, ts, te; + int ph, uh; /* Falling deeper than one level or falling through the map is forbidden. This array */ /* includes the critical bit mask for every level: the bit for the current level and */ /* the level below, for the lowest level falling is completely forbidden */ const byte deep_fall[] = {0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0}; + ph = PLAYER_HEIGHT; + uh = UNIT_HEIGHT; + /* get coordinates of that unit */ z = unitnum / WIDTH / WIDTH; y = (unitnum / WIDTH) % WIDTH; @@ -194,6 +200,7 @@ /* prepare trace */ VectorSet(pos, x, y, z); PosToVec(pos, start); + /* Adjust height to actual floor height. */ start[2] += h * QUANT; VectorCopy(start, ts); @@ -229,7 +236,7 @@ break; } /* range check*/ - if ( x < 0 || x >= WIDTH || y < 0 || y >= WIDTH) + if ( ax < 0 || ax >= WIDTH || ay < 0 || ay >= WIDTH) continue; /* height check */ if ((route[sz][ay][ax] & 0x0F) > h) @@ -241,6 +248,9 @@ if ((fall[ay][ax] & deep_fall[sz]) == deep_fall[sz]) continue; + /* Create the end point of the line to test. */ + VectorAdd(start, move_vec[i], te); + /* test for walls */ VectorAdd(start, move_vec[i], te); @@ -254,17 +264,66 @@ continue; route[z][y][x] |= 1 << (i + 4); - } } +} +/** + * @build Dumps contents of a map to file for inspection. + */ + /* + * Description of file contents: + * Each file is one layer of the map. Layer 0 is the bottom-most layer and increases going up. + * e.g. mine.4.csv is the 5th layer (0 is the 1st) from the bottom of the map. + * Each cell correspondes to one field unit. The cells in the file are aligned with + * the map orientation. n,s,e, and w indicate that a cell can be left from that direction. + * X indicates the cell is filled and cannot be entered. + * S indicates that block is a "step up" block and allows a character to leave to a much + * higher block that would otherwise be possible. + * F indicates that if an actor enters that cell, it will fall one layer. + * NOTE: 0,0 is the bottom, left corner. Y increases up; X increases right. + */ +void DumpMap (const char *filename) +{ + int x, y, z, zmask; + FILE *handle; + char newfilename[1024]; + for (z = HEIGHT - 1; z >= 0; --z) { + zmask = 1 << z; /* shorthand value */ + /*Prepare the filename for this layer */ + strcpy(newfilename,filename); + strcat(newfilename,".%i.csv",z); + + Com_Printf("Writing pathing dump file %s\n", newfilename); + + handle = fopen(newfilename,"w"); + fprintf(handle, "\n"); + for (y = WIDTH - 1; y >= 0; --y) { + for (x = 0; x < WIDTH; ++x) { + fprintf(handle, "%s%s%s%s%s%s%s%i," + , (route[z][y][x] & 0x20) ? "w" : " " + , (route[z][y][x] & 0x80) ? "s" : " " + , (route[z][y][x] & 0x40) ? "n" : " " + , (route[z][y][x] & 0x10) ? "e" : " " + , (filled[(y)][(x)] & zmask) ? "X" : " " + , (step[(y)][(x)] & zmask) ? "S" : " " + , (fall[(y)][(x)] & zmask) ? "F" : " " + , (route[z][y][x] & 0x0F)); + } + fprintf(handle, "\n"); + } + fclose(handle); + } +} + + /** * @brief Calculates the routing of a map * @sa CheckUnit * @sa CheckConnections * @sa ProcessWorldModel */ -void DoRouting (void) +void DoRouting (const char *filename) { int i; byte *data; @@ -303,7 +362,7 @@ wpMaxs[i] = ROUTING_NOT_REACHABLE; } -/* Com_Printf("(%i %i %i) (%i %i %i)\n", wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]); */ +/* fprintf(handle, "(%i %i %i) (%i %i %i)\n", wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]); */ /* scan area heights */ U2M_ProgressBar(CheckUnit, HEIGHT * WIDTH * WIDTH, qtrue, "UNITCHECK"); @@ -311,6 +370,11 @@ /* scan connections */ U2M_ProgressBar(CheckConnections, HEIGHT * WIDTH * WIDTH, qtrue, "CONNCHECK"); +#if 1 + /* This creates a pathing dump file */ + DumpMap(filename); +#endif + /* store the data */ data = droutedata; *data++ = SH_LOW;