All pastes #925597 Raw Edit

ufo:ai patch fixes pathing

public text v1 · immutable
·published 2008-03-03 03:50 UTC
rendered paste body
Index: client/cl_le.c
===================================================================
--- client/cl_le.c	(revision 15541)
+++ client/cl_le.c	(working copy)
@@ -190,7 +190,11 @@
 
 	le->inuse = qfalse;
 
+	/* 	Recalc the client routing table!!! */
+	CL_CompleteRecalcRouting();
+	/* Now look for paths! */
 	CL_ConditionalMoveCalc(&clMap, selActor, MAX_ROUTE);
+
 }
 
 /**
Index: common/cmodel.c
===================================================================
--- common/cmodel.c	(revision 15541)
+++ common/cmodel.c	(working copy)
@@ -122,7 +122,7 @@
 } mapTile_t;
 
 /**
- * @brief Pathfinding routing structure
+ * @brief Pathfinding routing structure and tile layout
  * @note Comments strongly WIP!
  *
  * ROUTE
@@ -159,6 +159,17 @@
  * AREASTORED
  * 	The stored mask (the cached move) of the routing data. (See Grid_MoveLength)
  *
+ * TILE LAYOUT AND PATHING
+ *  Maps are comprised of tiles.  Each tile has a number of levels corresponding to entities in game.
+ *  All static entities in the tile are located in levels 0-255, with the main world located in 0.
+ *  Levels 256-258 are reserved, see LEVEL_* constants in src/shared/shared.h.  Non-static entities
+ *  (ET_BREAKABLE and ET_ROTATING, ET_DOOR, etc.) are contained in levels 259 and above. These entities'
+ *  models are named *##, beginning from 1, and each corresponds to level LEVEL_STEPON + ##.
+ *
+ *  The code that handles the pathing has separate checks for the static and non-static levels in a tile.
+ *  The static levels have their bounds precalculated by CM_MakeTracingNodes and stored in tile->theads.
+ *  The other levels are checked in the fly when Grid_CheckUnit is called.
+ *
  */
 typedef struct routing_s {
 	byte route[HEIGHT][WIDTH][WIDTH];
@@ -803,11 +814,17 @@
 	/* get step height and trace vectors */
 	sh = R_STEP(map, x, y, z) ? sh_big : sh_low;
 	h = R_HEIGHT(map, x, y, z);
+
+	/* Setup the points used to check for walls and such */
 	VectorSet(pos, x, y, z);
 	PosToVec(pos, start);
-	start[2] += h * 4;
+	/* Adjust height to actual floor plus stepping height. */
+	start[2] += h * 4 - UNIT_HEIGHT / 2 + sh * 4;
+	/*Set the end point to the edge of the field unit in the direction traveling, accounting for "step up" */
+	/** TODO: should this check into the center of the adjacent field unit insead of just to the edge? */
 	VectorSet(end, start[0] + (UNIT_HEIGHT / 2) * dvecs[dir][0], start[1] + (UNIT_HEIGHT / 2) * dvecs[dir][1], start[2]);
 
+
 	ax = x + dvecs[dir][0];
 	assert((ax >= 0) && (ax < WIDTH));
 	ay = y + dvecs[dir][1];
@@ -831,14 +848,15 @@
 	if (R_HEIGHT(map, ax, ay, az) > h)
 		return;
 
-	/* center check */
-	if (CM_EntTestLine(start, end))
-		return;
+	/* Run multiple line tests to ensure that we can move between field units */
+	/** TODO: Do we need to use a bounding box to check for things in the way of this move? */
 
-	/* lower check */
-	start[2] = end[2] -= UNIT_HEIGHT / 2 - sh * 4 - 2;
-	if (CM_EntTestLine(start, end))
-		return;
+	for (h = sh * 4; h < PLAYER_HEIGHT; h += 4) {
+		if (CM_EntTestLine(start, end))
+			return;
+		/* raise check points */
+		start[2] = end[2] += 4;
+	}
 
 	/* allow connection to neighbor field */
 	map->route[z][y][x] |= (0x10 << dir) & UCHAR_MAX;
@@ -2433,6 +2451,45 @@
 */
 
 /**
+ * @build  Dumps contents of a map to console for inspection.
+ * @sa Grid_RecalcRouting
+ * @param[in] map The routing map (either server or client map)
+ * @param[in] lx  The low end of the x range updated
+ * @param[in] ly  The low end of the y range updated
+ * @param[in] lz  The low end of the z range updated
+ * @param[in] hx  The high end of the x range updated
+ * @param[in] hy  The high end of the y range updated
+ * @param[in] hz  The high end of the z range updated
+ */
+void Grid_DumpMap (struct routing_s *map, int lx, int ly, int lz, int hx, int hy, int hz)
+{
+    int x, y, z;
+
+    Com_Printf("\nGrid_DumpMap (%i %i %i) (%i %i %i)\n", lx, ly, lz, hx, hy, hz);
+    for (z = hz; z >= lz; --z) {
+        Com_Printf("\nLayer %i:\n    ", z);
+        for (x = lx; x <= hx; ++x) {
+            Com_Printf("%9i", x);
+        }
+		Com_Printf("\n");
+        for (y = hy; y >= ly; --y) {
+            Com_Printf("%3i ", y);
+            for (x = lx; x <= hx; ++x) {
+                Com_Printf("%s%s%s%s%s%s%2i "
+                    , R_CONN_NX(map, x, y, z) ? "w" : " "
+                    , R_CONN_NY(map, x, y, z) ? "n" : " "
+                    , R_CONN_PY(map, x, y, z) ? "s" : " "
+                    , R_CONN_PX(map, x, y, z) ? "e" : " "
+                    , R_STEP(map, x, y, z) ? "S" : " "
+                    , R_FALL(map, x, y, z) ? "F" : " "
+                    , R_HEIGHT(map, x, y, z));
+            }
+			Com_Printf("\n");
+        }
+    }
+}
+
+/**
  * @brief Checks one field (square) on the grid of the given routing data (i.e. the map).
  * @param[in] map Routing data/map.
  * @param[in] x Field in x direction
@@ -3077,12 +3134,20 @@
 		(int)max[0], (int)max[1], (int)max[2]);
 #endif
 
+#ifdef DEBUG
+    Grid_DumpMap(map, (int)min[0], (int)min[1], (int)min[2], (int)max[0], (int)max[1], (int)max[2]);
+#endif
+
 	/* check unit heights */
 	for (z = min[2]; z < max[2]; z++)
 		for (y = min[1]; y < max[1]; y++)
 			for (x = min[0]; x < max[0]; x++)
 				CM_CheckUnit(map, x, y, z);
 
+#ifdef DEBUG
+    Grid_DumpMap(map, (int)min[0], (int)min[1], (int)min[2], (int)max[0], (int)max[1], (int)max[2]);
+#endif
+
 	/* check connections */
 	for (z = min[2]; z < max[2]; z++)
 		for (y = min[1]; y < max[1]; y++)
@@ -3091,6 +3156,10 @@
 				for (i = 0; i < BASE_DIRECTIONS; i++)
 					CM_UpdateConnection(map, x, y, z, i, qtrue);
 
+#ifdef DEBUG
+    Grid_DumpMap(map, (int)min[0], (int)min[1], (int)min[2], (int)max[0], (int)max[1], (int)max[2]);
+#endif
+
 	inlineList = NULL;
 }
 
Index: tools/ufo2map/routing.c
===================================================================
--- tools/ufo2map/routing.c	(revision 15541)
+++ tools/ufo2map/routing.c	(working copy)
@@ -169,6 +169,8 @@
 {
 	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;
 	/* Falling deeper than one level or falling through the map is forbidden. This array */
@@ -194,7 +196,8 @@
 	/* prepare trace */
 	VectorSet(pos, x, y, z);
 	PosToVec(pos, start);
-	start[2] += h * QUANT;
+	/* Adjust height to actual floor plus stepping height. */
+	start[2] += h * QUANT - UNIT_HEIGHT / 2 + sh * 4;
 	VectorCopy(start, ts);
 
 	sh = (step[y][x] & (1 << z)) ? SH_BIG : SH_LOW;
@@ -244,16 +247,16 @@
 		/* test for walls */
 		VectorAdd(start, move_vec[i], te);
 
-		/* center check */
-		if (TestLineMask(start, te, 2))
-			continue;
-
-		/* lower check */
-		ts[2] = te[2] -= UNIT_HEIGHT / 2 - sh * QUANT - 2;
-		if (TestLineMask(ts, te, 2))
-			continue;
-
-		route[z][y][x] |= 1 << (i + 4);
+		/* Check at multiple height levels */
+		for (hc = sh * QUANT, vacant = qtrue; hc < PLAYER_HEIGHT && vacant; hc+=4) {
+			/* perform check */
+			if (TestLineMask(ts, te, 2))
+				vacant=qfalse;
+			/* raise checking points */
+			ts[2] = te[2] += 4;
+		}
+		if (vacant)
+			route[z][y][x] |= 1 << (i + 4);
 	}
 }