[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