[Scummvm-git-logs] scummvm master -> 49f317dd92d73c1f47ae3dfae8298c0fa2e457da

OMGPizzaGuy noreply at scummvm.org
Thu Oct 12 00:17:29 UTC 2023


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

Summary:
49f317dd92 ULTIMA8: Change supported position to require land below center of actors.


Commit: 49f317dd92d73c1f47ae3dfae8298c0fa2e457da
    https://github.com/scummvm/scummvm/commit/49f317dd92d73c1f47ae3dfae8298c0fa2e457da
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2023-10-11T19:17:05-05:00

Commit Message:
ULTIMA8: Change supported position to require land below center of actors.
This is closer to orginal game behavior and should resolve a few movement issues.

Changed paths:
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/animation_tracker.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/gravity_process.cpp
    engines/ultima/ultima8/world/position_info.h


diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 88382241cf4..d2159a1b4a0 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -625,30 +625,21 @@ Animation::Result Actor::tryAnim(Animation::Sequence anim, Direction dir,
 		state->_direction = dir;
 	}
 
-
 	if (tracker.isUnsupported()) {
 		return Animation::END_OFF_LAND;
 	}
 
 	// isUnsupported only checks for AFF_ONGROUND, we need either
-	int32 end[3], dims[3];
-	getFootpadWorld(dims[0], dims[1], dims[2]);
-	tracker.getPosition(end[0], end[1], end[2]);
+	Box start = getWorldBox();
+	Box target = start;
+	tracker.getPosition(target._x, target._y, target._z);
 
 	CurrentMap *cm = World::get_instance()->getCurrentMap();
+	PositionInfo info = cm->getPositionInfo(target, start, getShapeInfo()->_flags, _objId);
+	if (!info.supported)
+		return Animation::END_OFF_LAND;
 
-	UCList uclist(2);
-	LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
-	cm->surfaceSearch(&uclist, script, sizeof(script),
-	                  getObjId(), end, dims,
-	                  false, true, false);
-	for (uint32 i = 0; i < uclist.getSize(); i++) {
-		Item *item = getItem(uclist.getuint16(i));
-		if (item->getShapeInfo()->is_land())
-			return Animation::SUCCESS;
-	}
-
-	return Animation::END_OFF_LAND;
+	return Animation::SUCCESS;
 }
 
 DirectionMode Actor::animDirMode(Animation::Sequence anim) const {
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index b9d0e7fe724..818b3375bc9 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -313,7 +313,7 @@ bool AnimationTracker::step() {
 
 	if (is_u8 && info.valid && info.supported) {
 		// Might need to check for bridge traversal adjustments
-		uint32 supportshape = info.floor->getShape();
+		uint32 supportshape = info.land->getShape();
 		if (supportshape >= 675 && supportshape <= 681) {
 			// Could be a sloping portion of a bridge.  For a bridge along the
 			// X axis, positive descent delta is a positive change in Y when
@@ -328,13 +328,13 @@ bool AnimationTracker::step() {
 				descentdelta = -20;         // Descend
 
 			if (descentdelta) {
-				if (dy == 0 && dx != 0 && !info.floor->hasFlags(Item::FLG_FLIPPED)) {
+				if (dy == 0 && dx != 0 && !info.land->hasFlags(Item::FLG_FLIPPED)) {
 					// Moving left or right on horizontal bridge
 					// descentdelta = 60*dy/dx
 					// 60*dy = descentdelta * dx
 					// dy = descentdelta * dx / 60;
 					ty += descentdelta * dx / 60;
-				} else if (dx == 0 && dy != 0 && info.floor->hasFlags(Item::FLG_FLIPPED)) {
+				} else if (dx == 0 && dy != 0 && info.land->hasFlags(Item::FLG_FLIPPED)) {
 					// Moving up or down on vertical bridge
 					tx += descentdelta * dy / 60;
 				}
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 129e268b870..27d0b85930e 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -741,13 +741,18 @@ PositionInfo CurrentMap::getPositionInfo(int32 x, int32 y, int32 z, uint32 shape
 
 PositionInfo CurrentMap::getPositionInfo(const Box &target, const Box &start, uint32 shapeflags, ObjId id) const {
 	PositionInfo info;
-	static const uint32 flagmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_DAMAGING |
-	                         ShapeInfo::SI_ROOF);
-	static const uint32 blockflagmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_DAMAGING);
+	static const uint32 flagmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_DAMAGING | ShapeInfo::SI_LAND | ShapeInfo::SI_ROOF);
+	static const uint32 supportmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_LAND | ShapeInfo::SI_ROOF);
+	static const uint32 landmask = (ShapeInfo::SI_LAND | ShapeInfo::SI_ROOF);
+	static const uint32 blockmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_DAMAGING);
 
-	int32 floorz = INT_MIN_VALUE;
+	int32 supportz = INT_MIN_VALUE;
+	int32 landz = INT_MIN_VALUE;
 	int32 roofz = INT_MAX_VALUE;
 
+	int32 midx = target._x - target._xd / 2;
+	int32 midy = target._y - target._yd / 2;
+
 	int minx = ((target._x - target._xd) / _mapChunkSize) - 1;
 	int maxx = (target._x / _mapChunkSize) + 1;
 	int miny = ((target._y - target._yd) / _mapChunkSize) - 1;
@@ -766,14 +771,13 @@ PositionInfo CurrentMap::getPositionInfo(const Box &target, const Box &start, ui
 					continue;
 
 				const ShapeInfo *si = item->getShapeInfo();
-				//!! need to check is_sea() and is_land() maybe?
 				if (!(si->_flags & flagmask))
 					continue; // not an interesting item
 
 				Box ib = item->getWorldBox();
 
 				// check overlap
-				if ((si->_flags & shapeflags & blockflagmask) &&
+				if ((si->_flags & shapeflags & blockmask) &&
 					target.overlaps(ib) && !start.overlaps(ib)) {
 					// overlapping an item. Invalid position
 #if 0
@@ -787,10 +791,9 @@ PositionInfo CurrentMap::getPositionInfo(const Box &target, const Box &start, ui
 				// check xy overlap
 				if (target._x > ib._x - ib._xd && target._x - target._xd < ib._x &&
 					target._y > ib._y - ib._yd && target._y - target._yd < ib._y) {
-					// check floor
-					if (si->is_solid() && ib._z + ib._zd > floorz && ib._z + ib._zd <= target._z) {
-						info.floor = item;
-						floorz = ib._z + ib._zd;
+					// check support
+					if (si->_flags & supportmask && ib._z + ib._zd > supportz && ib._z + ib._zd <= target._z) {
+						supportz = ib._z + ib._zd;
 					}
 
 					// check roof
@@ -799,12 +802,22 @@ PositionInfo CurrentMap::getPositionInfo(const Box &target, const Box &start, ui
 						roofz = ib._z;
 					}
 				}
+
+				// check xy center
+				if (midx >= ib._x - ib._xd && midx <= ib._x && midy >= ib._y - ib._yd && midy <= ib._y) {
+					// check land
+					if (si->_flags & landmask && ib._z + ib._zd > landz && ib._z + ib._zd <= target._z) {
+						info.land = item;
+						landz = ib._z + ib._zd;
+					}
+				}
 			}
 		}
 	}
 
 	info.valid = info.blocker == nullptr;
-	info.supported = floorz == target._z;
+	// Partial support allowed if land is close
+	info.supported = supportz == target._z && landz + 8 >= target._z;
 	return info;
 }
 
diff --git a/engines/ultima/ultima8/world/gravity_process.cpp b/engines/ultima/ultima8/world/gravity_process.cpp
index 360fa611c94..ab5bbc0c675 100644
--- a/engines/ultima/ultima8/world/gravity_process.cpp
+++ b/engines/ultima/ultima8/world/gravity_process.cpp
@@ -27,6 +27,8 @@
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/world/actors/actor_anim_process.h"
 #include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/world/current_map.h"
+#include "ultima/ultima8/world/world.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -148,7 +150,32 @@ void GravityProcess::run() {
 		Item *hititem = getItem(hititemid);
 		if (!hititem)
 			return; // shouldn't happen..
-		if (_zSpeed < -2 && !dynamic_cast<Actor *>(item)) {
+
+		CurrentMap *cm = World::get_instance()->getCurrentMap();
+		Box target = item->getWorldBox();
+		Box empty;
+		PositionInfo info = cm->getPositionInfo(target, empty, item->getShapeInfo()->_flags, _itemNum);
+		if (!info.valid || !info.supported) {
+			// Reset speed and continue to slip off
+			termFlag = false;
+			_zSpeed = 0;
+
+			item->getCentre(ix, iy, iz);
+			target = hititem->getWorldBox();
+			if (ABS(_xSpeed) < 16) {
+				if (ix + 16 > target._x)
+					_xSpeed = 16;
+				else if (ix - 16 < target._x - target._xd)
+					_xSpeed = -16;
+			}
+
+			if (ABS(_ySpeed) < 16) {
+				if (iy + 16 > target._y)
+					_ySpeed = 16;
+				else if (iy - 16 < target._y - target._yd)
+					_ySpeed = -16;
+			}
+		} else if (_zSpeed < -2 && !actor) {
 #ifdef BOUNCE_DIAG
 			debugC(kDebugObject, "item %u bounce [%u]: hit %u",
 				_itemNum, Kernel::get_instance()->getFrameNum(), hititem->getObjId());
@@ -189,7 +216,8 @@ void GravityProcess::run() {
 					_xSpeed /= 4;
 					_ySpeed /= 4;
 					_zSpeed /= 2;
-					if (_zSpeed == 0) termFlag = true;
+					if (_zSpeed == 0)
+						termFlag = true;
 				} else {
 					// Not on land; this bounce approximates what's seen
 					// in the original U8 when Kilandra's daughters ghost
@@ -216,14 +244,15 @@ void GravityProcess::run() {
 				  _itemNum, Kernel::get_instance()->getFrameNum());
 #endif
 		}
+
 		if (termFlag) {
 			item->clearFlag(Item::FLG_BOUNCING);
 			terminateDeferred();
 		} else {
 			item->setFlag(Item::FLG_BOUNCING);
 		}
-		fallStopped();
 
+		fallStopped();
 	} else {
 
 		// blocked in some other direction than strictly downward
diff --git a/engines/ultima/ultima8/world/position_info.h b/engines/ultima/ultima8/world/position_info.h
index 0097d3921af..fc2a0968e2b 100644
--- a/engines/ultima/ultima8/world/position_info.h
+++ b/engines/ultima/ultima8/world/position_info.h
@@ -31,24 +31,24 @@ class Item;
  * Position information for a desired target box for an item.
  * The position is valid when the target box does not collide with any solid items.
  *
- * Floor is set to the solid item with the highest z coordinate under the target box,
- * or null if there is no floor below box.
+ * Land is set to the item with the highest z coordinate under the target box,
+ * or null if there is no land below box.
  * 
- * Roof is set to the roof item with the lowest z coordinate over the target box,
+ * Roof is set to the item with the lowest z coordinate over the target box,
  * or null if there is no roof above box.
  *
  * Blocker is set to an item blocking the target box, or null if there is no such item.
  *
- * Supported is true if the floor is appropriate to support the item when at the target.
+ * Supported is true if the land is appropriate to support the item when at the target.
  */
 struct PositionInfo {
 	bool valid;
 	bool supported;
-	const Item *floor;
+	const Item *land;
 	const Item *roof;
 	const Item *blocker;
 
-	PositionInfo() : valid(false), supported(false), floor(nullptr), roof(nullptr), blocker(nullptr) {}
+	PositionInfo() : valid(false), supported(false), land(nullptr), roof(nullptr), blocker(nullptr) {}
 };
 
 } // End of namespace Ultima8




More information about the Scummvm-git-logs mailing list