[Scummvm-git-logs] scummvm master -> 05c9ad13478d752a58c093a25b0ca53874fcf840

dreammaster noreply at scummvm.org
Sat Apr 1 22:59:17 UTC 2023


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
de42667d75 NUVIE: Fix Ultima 6 projectile collision
05c9ad1347 NUVIE: Rework Ultima 6 projectile collision fix


Commit: de42667d75bf50a7a6a37b64c4ae2def8f78ceef
    https://github.com/scummvm/scummvm/commit/de42667d75bf50a7a6a37b64c4ae2def8f78ceef
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2023-04-01T15:59:13-07:00

Commit Message:
NUVIE: Fix Ultima 6 projectile collision

Make the line drawing algorithm used in projectile collision detection
operate in screen space to match the original game.

Before this change the calculation was done in tile space, which caused
incorrect results.

Changed paths:
    engines/ultima/nuvie/core/map.cpp


diff --git a/engines/ultima/nuvie/core/map.cpp b/engines/ultima/nuvie/core/map.cpp
index f51d1792454..36b18a52619 100644
--- a/engines/ultima/nuvie/core/map.cpp
+++ b/engines/ultima/nuvie/core/map.cpp
@@ -762,16 +762,21 @@ bool Map::testIntersection(int x, int y, uint8 level, uint8 flags, LineTestResul
 bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
 				   uint8 flags, LineTestResult &Result, uint32 skip, Obj *excluded_obj) {
 	//  standard Bresenham's algorithm.
-	int deltax = abs(end_x - start_x);
-	int deltay = abs(end_y - start_y);
-
-	int x = start_x;
-	int y = start_y;
+	//  input tile coordinates are scaled up by 16 during line calculation
+	//  and scaled back down before testing for collisions. this matches original
+	//  game behaviour.
+	int deltax = abs(end_x - start_x) << 4;
+	int deltay = abs(end_y - start_y) << 4;
+
+	int x = (start_x << 4) + 8; // start at the center of the tile
+	int y = (start_y << 4) + 8;
 	int d;
 	int xinc1, xinc2;
 	int yinc1, yinc2;
 	int dinc1, dinc2;
 	uint32 count;
+	int xtile = start_x;
+	int ytile = start_y;
 
 
 	if (deltax >= deltay) {
@@ -806,10 +811,6 @@ bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
 	}
 
 	for (uint32 i = 0; i < count; i++) {
-		//  test the current location
-		if ((i >= skip) && (testIntersection(x, y, level, flags, Result, excluded_obj) == true))
-			return  true;
-
 		if (d < 0) {
 			d += dinc1;
 			x += xinc1;
@@ -819,6 +820,13 @@ bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
 			x += xinc2;
 			y += yinc2;
 		}
+		if( x >> 4 == xtile && y >> 4 == ytile)
+			continue; //  we are still on the previous tile so skip the test
+		xtile = x >> 4;
+		ytile = y >> 4;
+		//  test the current location
+		if ((i >= skip) && (testIntersection(xtile, ytile, level, flags, Result, excluded_obj) == true))
+			return true;
 	}
 
 	return  false;


Commit: 05c9ad13478d752a58c093a25b0ca53874fcf840
    https://github.com/scummvm/scummvm/commit/05c9ad13478d752a58c093a25b0ca53874fcf840
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2023-04-01T15:59:13-07:00

Commit Message:
NUVIE: Rework Ultima 6 projectile collision fix

Fix regressions by only scaling coordinates when handling projectiles.

Changed paths:
    engines/ultima/nuvie/core/map.cpp
    engines/ultima/nuvie/core/map.h
    engines/ultima/nuvie/script/script.cpp


diff --git a/engines/ultima/nuvie/core/map.cpp b/engines/ultima/nuvie/core/map.cpp
index 36b18a52619..382ed57a934 100644
--- a/engines/ultima/nuvie/core/map.cpp
+++ b/engines/ultima/nuvie/core/map.cpp
@@ -759,17 +759,22 @@ bool Map::testIntersection(int x, int y, uint8 level, uint8 flags, LineTestResul
 
 //	returns true if a line hits something travelling from (start_x, start_y) to
 //	(end_x, end_y).  If a hit occurs Result is filled in with the relevant info.
+//	If want_screen_space is true input tile coordinates are multiplied by 16 for
+//	line calculation and scaled back down before testing for collisions. The
+//	original game does this for projectiles.
 bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
-				   uint8 flags, LineTestResult &Result, uint32 skip, Obj *excluded_obj) {
+				   uint8 flags, LineTestResult &Result, uint32 skip, Obj *excluded_obj,
+				   bool want_screen_space) {
 	//  standard Bresenham's algorithm.
-	//  input tile coordinates are scaled up by 16 during line calculation
-	//  and scaled back down before testing for collisions. this matches original
-	//  game behaviour.
-	int deltax = abs(end_x - start_x) << 4;
-	int deltay = abs(end_y - start_y) << 4;
-
-	int x = (start_x << 4) + 8; // start at the center of the tile
-	int y = (start_y << 4) + 8;
+	uint8 scale_factor_log2 = 0;
+	if (want_screen_space)
+		scale_factor_log2 = 4; //  set scale factor to 16
+	int deltax = abs(end_x - start_x) << scale_factor_log2;
+	int deltay = abs(end_y - start_y) << scale_factor_log2;
+	int x = (start_x << scale_factor_log2);
+	int y = (start_y << scale_factor_log2);
+	x += ((1 << scale_factor_log2) >> 1); //  start at the center of the tile
+	y += ((1 << scale_factor_log2) >> 1); //  when in screen space
 	int d;
 	int xinc1, xinc2;
 	int yinc1, yinc2;
@@ -811,6 +816,15 @@ bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
 	}
 
 	for (uint32 i = 0; i < count; i++) {
+		//  only test for collision if tile coordinates have changed
+		if ((scale_factor_log2 == 0 || x >> scale_factor_log2 != xtile || y >> scale_factor_log2 != ytile)) {
+			xtile = x >> scale_factor_log2; //  scale back down to tile
+			ytile = y >> scale_factor_log2; //  space if necessary
+			//  test the current location
+			if ((i >= skip) && (testIntersection(xtile, ytile, level, flags, Result, excluded_obj) == true))
+				return true;
+		}
+
 		if (d < 0) {
 			d += dinc1;
 			x += xinc1;
@@ -820,13 +834,6 @@ bool Map::lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
 			x += xinc2;
 			y += yinc2;
 		}
-		if( x >> 4 == xtile && y >> 4 == ytile)
-			continue; //  we are still on the previous tile so skip the test
-		xtile = x >> 4;
-		ytile = y >> 4;
-		//  test the current location
-		if ((i >= skip) && (testIntersection(xtile, ytile, level, flags, Result, excluded_obj) == true))
-			return true;
 	}
 
 	return  false;
diff --git a/engines/ultima/nuvie/core/map.h b/engines/ultima/nuvie/core/map.h
index 11772d2929f..2032e1a9497 100644
--- a/engines/ultima/nuvie/core/map.h
+++ b/engines/ultima/nuvie/core/map.h
@@ -187,7 +187,7 @@ public:
 	const char *look(uint16 x, uint16 y, uint8 level);
 
 	bool lineTest(int start_x, int start_y, int end_x, int end_y, uint8 level,
-	              uint8 flags, LineTestResult &Result, uint32 skip = 0, Obj *excluded_obj = NULL); // excluded_obj only works for LT_HitUnpassable
+	              uint8 flags, LineTestResult &Result, uint32 skip = 0, Obj *excluded_obj = NULL, bool want_screen_space = false); // excluded_obj only works for LT_HitUnpassable
 
 	bool testIntersection(int x, int y, uint8 level, uint8 flags, LineTestResult &Result, Obj *excluded_obj = NULL); // excluded_obj only works for LT_HitUnpassable
 
diff --git a/engines/ultima/nuvie/script/script.cpp b/engines/ultima/nuvie/script/script.cpp
index 2263f171f6e..3da1c18c6ce 100644
--- a/engines/ultima/nuvie/script/script.cpp
+++ b/engines/ultima/nuvie/script/script.cpp
@@ -3168,7 +3168,7 @@ static int nscript_map_line_hit_check(lua_State *L) {
 	uint8 level = (uint8) luaL_checkinteger(L, 5);
 
 	//FIXME world wrapping for MD
-	if (map->lineTest(x, y, x1, y1, level, LT_HitMissileBoundary, result)) {
+	if (map->lineTest(x, y, x1, y1, level, LT_HitMissileBoundary, result, 0, NULL, true)) {
 		lua_pushinteger(L, result.hit_x);
 		lua_pushinteger(L, result.hit_y);
 	} else {




More information about the Scummvm-git-logs mailing list