/** * @brief This function recalculates the routing in and around the box bounded by min and max. * @sa CMod_LoadRouting * @sa Grid_RecalcRouting * @param[in] mapTiles List of tiles the current (RMA-)map is composed of * @param[in] routing The routing map (either server or client map) * @param[in] box The box to recalc routing for * @param[in] list The local models list (a local model has a name starting with * followed by the model number) */ void Grid_RecalcBoxRouting (mapTiles_t *mapTiles, Routing &routing, const GridBox &box, const char **list) { int x, y, z, actorSize, dir; /* check unit heights */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { GridBox rBox(box); /* the box we will actually reroute */ /* Offset the initial X and Y to compensate for larger actors when needed. */ rBox.expandXY(actorSize - 1); /* also start one level above the box to measure high floors correctly */ rBox.addOneZ(); for (y = rBox.mins[1]; y <= rBox.maxs[1]; y++) { for (x = rBox.mins[0]; x <= rBox.maxs[0]; x++) { /** @note RT_CheckCell goes from top (7) to bottom (0) */ for (z = rBox.maxs[2]; z >= 0; z--) { const int newZ = RT_CheckCell(mapTiles, routing, actorSize, x, y, z, list); assert(newZ <= z); z = newZ; } } } } /* check connections */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { GridBox rBox(box); /* the box we will actually reroute */ rBox.expandXY(actorSize); /* for connections, expand by the full size of the actor */ for (y = rBox.mins[1]; y <= rBox.maxs[1]; y++) { for (x = rBox.mins[0]; x <= rBox.maxs[0]; x++) { for (dir = 0; dir < CORE_DIRECTIONS; dir++) { /** @note The new version of RT_UpdateConnectionColumn can work bidirectional, so we can * trace every other dir, unless we are on the edge. */ #if RT_IS_BIDIRECTIONAL == 1 if ((dir & 1) && x != minX && x != maxX && y != minY && y != maxY) continue; #endif /* for places outside the model box, skip dirs that can not be affected by the model */ if (x > box.maxs[0] && dir != 1 && dir != 5 && dir != 6) continue; if (y > box.maxs[1] && dir != 3 && dir != 5 && dir != 7) continue; if (actorSize == ACTOR_SIZE_NORMAL) { if (x < box.mins[0] && dir != 0 && dir != 4 && dir != 7) continue; if (y < box.mins[1] && dir != 2 && dir != 4 && dir != 6) continue; } else { /* the position of 2x2 actors is their lower left cell */ if (x < box.mins[0] - 1 && dir != 0 && dir != 4 && dir != 7) continue; if (y < box.mins[1] - 1 && dir != 2 && dir != 4 && dir != 6) continue; } RT_UpdateConnectionColumn(mapTiles, routing, actorSize, x, y, dir, list); } } } } }
/** * @brief This function recalculates the routing in and around the box bounded by min and max. * @sa CMod_LoadRouting * @sa Grid_RecalcRouting * @param[in] mapTiles List of tiles the current (RMA-)map is composed of * @param[in] routing The routing map (either server or client map) * @param[in] box The box to recalc routing for * @param[in] list The local models list (a local model has a name starting with * followed by the model number) */ void Grid_RecalcBoxRouting (mapTiles_t* mapTiles, Routing& routing, const GridBox& box, const char** list) { int x, y, z, actorSize, dir; /* check unit heights */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { GridBox rBox(box); /* the box we will actually reroute */ /* Offset the initial X and Y to compensate for larger actors when needed. */ rBox.expandXY(actorSize - 1); /* also start one level above the box to measure high floors correctly */ rBox.addOneZ(); for (y = rBox.getMinY(); y <= rBox.getMaxY(); y++) { for (x = rBox.getMinX(); x <= rBox.getMaxX(); x++) { /** @note RT_CheckCell goes from top (7) to bottom (0) */ for (z = rBox.getMaxZ(); z >= 0; z--) { const int newZ = RT_CheckCell(mapTiles, routing, actorSize, x, y, z, list); assert(newZ <= z); z = newZ; } } } } /* check connections */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { GridBox rBox(box); /* the box we will actually reroute */ rBox.expandXY(actorSize); /* for connections, expand by the full size of the actor */ rBox.addOneZ(); for (y = rBox.getMinY(); y <= rBox.getMaxY(); y++) { for (x = rBox.getMinX(); x <= rBox.getMaxX(); x++) { for (dir = 0; dir < CORE_DIRECTIONS; dir++) { /* for places outside the model box, skip dirs that can not be affected by the model */ if (x > box.getMaxX() && dir != 1 && dir != 5 && dir != 6) continue; if (y > box.getMaxY() && dir != 3 && dir != 5 && dir != 7) continue; if (actorSize == ACTOR_SIZE_NORMAL) { if (x < box.getMinX() && dir != 0 && dir != 4 && dir != 7) continue; if (y < box.getMinY() && dir != 2 && dir != 4 && dir != 6) continue; } else { /* the position of 2x2 actors is their lower left cell */ if (x < box.getMinX() - 1 && dir != 0 && dir != 4 && dir != 7) continue; if (y < box.getMinY() - 1 && dir != 2 && dir != 4 && dir != 6) continue; } // RT_UpdateConnectionColumn(mapTiles, routing, actorSize, x, y, dir, list); RT_UpdateConnectionColumn(mapTiles, routing, actorSize, x, y, dir, list, rBox.getMinZ(), rBox.getMaxZ()); } } } } }
/** * @brief This function recalculates the routing in the box bounded by min and max. * @sa CMod_LoadRouting * @sa Grid_RecalcRouting * @param[in] mapTiles List of tiles the current (RMA-)map is composed of * @param[in] map The routing map (either server or client map) * @param[in] min The lower extents of the box to recalc routing for * @param[in] max The upper extents of the box to recalc routing for * @param[in] list The local models list (a local model has a name starting with * followed by the model number) */ void Grid_RecalcBoxRouting (mapTiles_t *mapTiles, routing_t *map, const pos3_t min, const pos3_t max, const char **list) { int x, y, z, actorSize, dir; Com_DPrintf(DEBUG_PATHING, "rerouting (%i %i %i) (%i %i %i)\n", (int)min[0], (int)min[1], (int)min[2], (int)max[0], (int)max[1], (int)max[2]); /* check unit heights */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { const int maxY = max[1] + actorSize; const int maxX = max[0] + actorSize; /* Offset the initial X and Y to compensate for larger actors when needed. */ for (y = max(min[1] - actorSize + 1, 0); y < maxY; y++) { for (x = max(min[0] - actorSize + 1, 0); x < maxX; x++) { /** @note RT_CheckCell goes from top (7) to bottom (0) */ for (z = max[2]; z >= 0; z--) { const int newZ = RT_CheckCell(mapTiles, map, actorSize, x, y, z, list); assert(newZ <= z); z = newZ; } } } } /* check connections */ for (actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) { const int minX = max(min[0] - actorSize, 0); const int minY = max(min[1] - actorSize, 0); const int maxX = min(max[0] + actorSize, PATHFINDING_WIDTH - 1); const int maxY = min(max[1] + actorSize, PATHFINDING_WIDTH - 1); /* Offset the initial X and Y to compensate for larger actors when needed. * Also sweep further out to catch the walls back into our box. */ for (y = minY; y <= maxY; y++) { for (x = minX; x <= maxX; x++) { for (dir = 0; dir < CORE_DIRECTIONS; dir++) { /** @note The new version of RT_UpdateConnectionColumn can work bidirectional, so we can * trace every other dir, unless we are on the edge. */ #if RT_IS_BIDIRECTIONAL == 1 if ((dir & 1) && x != minX && x != maxX && y != minY && y != maxY) continue; #endif RT_UpdateConnectionColumn(mapTiles, map, actorSize, x, y, dir, list); } } } } }
/** * @sa DoRouting */ static void CheckConnectionsThread (unsigned int unitnum) { /* get coordinates of that unit */ const int numDirs = CORE_DIRECTIONS / (1 + RT_IS_BIDIRECTIONAL); const int dir = (unitnum % numDirs) * (RT_IS_BIDIRECTIONAL ? 2 : 1); const int y = (unitnum / numDirs) % PATHFINDING_WIDTH; const int x = (unitnum / numDirs / PATHFINDING_WIDTH) % PATHFINDING_WIDTH; const int actorSize = unitnum / numDirs / PATHFINDING_WIDTH / PATHFINDING_WIDTH; /* test bounds - the size adjustment is needed because large actor cells occupy multiple cell units. */ if (x > wpMaxs[0] - actorSize || y > wpMaxs[1] - actorSize || x < wpMins[0] || y < wpMins[1] ) { /* don't enter - outside world */ /* Com_Printf("x%i y%i z%i dir%i size%i (%i, %i, %i) (%i, %i, %i)\n", x, y, z, dir, size, wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]); */ return; } Verb_Printf(VERB_EXTRA, "%i %i %i %i (%i, %i, %i) (%i, %i, %i)\n", x, y, dir, actorSize, wpMins[0], wpMins[1], wpMins[2], wpMaxs[0], wpMaxs[1], wpMaxs[2]); RT_UpdateConnectionColumn(&mapTiles, Nmap, actorSize + 1, x, y, dir); /* Com_Printf("z:%i nz:%i\n", z, new_z); */ }