[Scummvm-git-logs] scummvm master -> 8d88e7b4d5b6ed22288d63709d2766e4eaa713b9

athrxx noreply at scummvm.org
Fri Jul 19 22:39:24 UTC 2024


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:
8d88e7b4d5 SCUMM: (V1/2) - fix bug no. 15273


Commit: 8d88e7b4d5b6ed22288d63709d2766e4eaa713b9
    https://github.com/scummvm/scummvm/commit/8d88e7b4d5b6ed22288d63709d2766e4eaa713b9
Author: athrxx (athrxx at scummvm.org)
Date: 2024-07-20T00:38:58+02:00

Commit Message:
SCUMM: (V1/2) - fix bug no. 15273

(Walking animation when turning not correct)

Also match v1/2 walk code more to the orginal behavior
in general, to eliminate accuracy glitches.

Also, get rid of memory leaks in resetScumm().

Changed paths:
    engines/scumm/actor.cpp
    engines/scumm/actor.h
    engines/scumm/scumm.cpp


diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index afffc8d9bb9..00345d36bd3 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -581,8 +581,11 @@ int Actor::calcMovementFactor(const Common::Point& next) {
 int Actor_v3::calcMovementFactor(const Common::Point& next) {
 	int32 deltaXFactor, deltaYFactor;
 
-	if (_pos == next)
+	if (_pos == next) {
+		if (_vm->_game.version == 2)
+			_moving |= MF_IN_LEG;
 		return 0;
+	}
 
 	int diffX = next.x - _pos.x;
 	int diffY = next.y - _pos.y;
@@ -611,14 +614,23 @@ int Actor_v3::calcMovementFactor(const Common::Point& next) {
 	_walkdata.next = next;
 	_walkdata.deltaXFactor = deltaXFactor;
 	_walkdata.deltaYFactor = deltaYFactor;
+	_walkdata.facing = diffX >= 0 ? (diffY >= 0 ? 1 : 0) : (diffY >= 0 ? 2 : 3);
 
 	// The x/y distance ratio which determines whether to face up/down instead of left/right is different for SCUMM1/2 and SCUMM3.
 	_targetFacing = oldDirToNewDir(((ABS(diffY) * _facingXYratio) > ABS(diffX)) ? 3 - (diffY >= 0 ? 1 : 0) : (diffX >= 0 ? 1 : 0));
 
-	if (_vm->_game.version <= 2 && _facing != updateActorDirection(true))
+	if (_vm->_game.version > 2)
+		return actorWalkStep();
+
+	_moving &= ~MF_IN_LEG;
+	if (_facing != _targetFacing)
 		_moving |= MF_TURN;
 
-	return actorWalkStep();
+
+	if (_walkFrame != _frame || _facing != _targetFacing)
+		startWalkAnim(1, _facing);
+
+	return (_moving & MF_TURN) ? 0 : actorWalkStep();
 }
 
 int Actor::actorWalkStep() {
@@ -672,6 +684,26 @@ int Actor::actorWalkStep() {
 	return 1;
 }
 
+int Actor_v2::actorWalkStep() {
+	_needRedraw = true;
+
+	if ((_walkdata.xfrac += _walkdata.xAdd) >= _stepThreshold) {
+		if (_pos.x != _walkdata.next.x)
+			_pos.x += _walkdata.deltaXFactor;
+		_walkdata.xfrac -= _stepThreshold;
+	}
+	if ((_walkdata.yfrac += _walkdata.yAdd) >= _stepThreshold) {
+		if (_pos.y != _walkdata.next.y)
+			_pos.y += _walkdata.deltaYFactor;
+		_walkdata.yfrac -= _stepThreshold;
+	}
+
+	if (_pos == _walkdata.next)
+		_moving |= MF_IN_LEG;
+
+	return 0;
+}
+
 int Actor_v3::actorWalkStep() {
 	_needRedraw = true;
 
@@ -681,28 +713,21 @@ int Actor_v3::actorWalkStep() {
 			startWalkAnim(1, nextFacing);
 
 		_moving |= MF_IN_LEG;
-		// The next two lines fix bug #12278 for ZAK FM-TOWNS (SCUMM3). They are alse required for SCUMM 1/2 to prevent movement while
-		// turning, but only if the character has to make a turn. The correct behavior for v1/2 can be tested by letting Zak (only v1/2
-		// versions) walk in the starting room from the torn wallpaper to the desk drawer: Zak should first turn around clockwise by
-		// 180°, then walk one step to the left, then turn clockwise 90°. For ZAK FM-TOWNS (SCUMM3) this part will look quite different
-		// (and a bit weird), but I have confirmed the correctness with the FM-Towns emulator, too.
-		if (_vm->_game.version == 3 || (_vm->_game.version <= 2 && (_moving & MF_TURN)))
-			return 1;
+		// The next line fixes bug #12278 for ZAK FM-TOWNS (SCUMM3).
+		return 1;
 	}
 
-	if (_vm->_game.version == 3) {
-		if (_walkdata.next.x - (int)_stepX <= _pos.x && _walkdata.next.x + (int)_stepX >= _pos.x)
-			_pos.x = _walkdata.next.x;
-		if (_walkdata.next.y - (int)_speedy <= _pos.y && _walkdata.next.y + (int)_speedy >= _pos.y)
-			_pos.y = _walkdata.next.y;
+	if (_walkdata.next.x - (int)_stepX <= _pos.x && _walkdata.next.x + (int)_stepX >= _pos.x)
+		_pos.x = _walkdata.next.x;
+	if (_walkdata.next.y - (int)_speedy <= _pos.y && _walkdata.next.y + (int)_speedy >= _pos.y)
+		_pos.y = _walkdata.next.y;
 
-		if (_walkbox != _walkdata.curbox && _vm->checkXYInBoxBounds(_walkdata.curbox, _pos.x, _pos.y))
-			setBox(_walkdata.curbox);
+	if (_walkbox != _walkdata.curbox && _vm->checkXYInBoxBounds(_walkdata.curbox, _pos.x, _pos.y))
+		setBox(_walkdata.curbox);
 
-		if (_pos == _walkdata.next) {
-			_moving &= ~MF_IN_LEG;
-			return 0;
-		}
+	if (_pos == _walkdata.next) {
+		_moving &= ~MF_IN_LEG;
+		return 0;
 	}
 
 	if ((_walkdata.xfrac += _walkdata.xAdd) >= _stepThreshold) {
@@ -716,11 +741,6 @@ int Actor_v3::actorWalkStep() {
 		_walkdata.yfrac -= _stepThreshold;
 	}
 
-	if (_vm->_game.version <= 2 && _pos == _walkdata.next) {
-		_moving &= ~MF_IN_LEG;
-		return 0;
-	}
-
 	return 1;
 }
 
@@ -892,7 +912,7 @@ void Actor::startWalkActor(int destX, int destY, int dir) {
 		((Actor_v0 *)this)->walkBoxQueuePrepare();
 
 	} else if (_vm->_game.version <= 2) {
-		_moving = (_moving & ~(MF_LAST_LEG | MF_IN_LEG)) | MF_NEW_LEG;
+		_moving = (_moving & ~MF_LAST_LEG) | MF_IN_LEG | MF_NEW_LEG;
 	} else {
 		_moving = (_moving & MF_IN_LEG) | MF_NEW_LEG;
 	}
@@ -1230,50 +1250,46 @@ UpdateActorDirection:;
 }
 
 void Actor_v2::walkActor() {
-	Common::Point foundPath, tmp;
-	int new_dir, next_box;
-
 	if (_moving & MF_TURN) {
-		new_dir = updateActorDirection(false);
-		if (_facing != new_dir) {
-			setDirection(new_dir);
-		} else {
+		int newDir = updateActorDirection(false);
+		if (_targetFacing == newDir)
 			_moving &= ~MF_TURN;
-		}
+		setDirection(newDir);
 		return;
 	}
 
-	if (!_moving)
+	if (!(_moving & MF_NEW_LEG))
 		return;
 
-	if (_moving & MF_IN_LEG) {
+	if (!(_moving & MF_IN_LEG)) {
 		actorWalkStep();
 	} else {
 		if (_moving & MF_LAST_LEG) {
 			_moving = MF_TURN;
 			startAnimActor(_standFrame);
-			if (_targetFacing != _walkdata.destdir)
+			if (_walkdata.destdir != -1)
 				turnToDirection(_walkdata.destdir);
 		} else {
+			Common::Point foundPath, tmp;
 			setBox(_walkdata.curbox);
 			if (_walkbox == _walkdata.destbox) {
 				foundPath = _walkdata.dest;
 				_moving |= MF_LAST_LEG;
 			} else {
-				next_box = _vm->getNextBox(_walkbox, _walkdata.destbox);
-				if (next_box < 0) {
+				int nextBox = _vm->getNextBox(_walkbox, _walkdata.destbox);
+				if (nextBox < 0) {
 					_moving |= MF_LAST_LEG;
 					return;
 				}
 
 				// Can't walk through locked boxes
-				int flags = _vm->getBoxFlags(next_box);
+				int flags = _vm->getBoxFlags(nextBox);
 				if ((flags & kBoxLocked) && !((flags & kBoxPlayerOnly) && !isPlayer())) {
 					_moving |= MF_LAST_LEG;
-					//_walkdata.destdir = -1;
+					_walkdata.destdir = -1;
 				}
 
-				_walkdata.curbox = next_box;
+				_walkdata.curbox = nextBox;
 
 				getClosestPtOnBox(_vm->getBoxCoordinates(_walkdata.curbox), _pos.x, _pos.y, tmp.x, tmp.y);
 				getClosestPtOnBox(_vm->getBoxCoordinates(_walkbox), tmp.x, tmp.y, foundPath.x, foundPath.y);
@@ -1495,6 +1511,39 @@ int Actor::remapDirection(int dir, bool is_walking) {
 	return dir;
 }
 
+int Actor_v2::remapDirection(int dir, bool is_walking) {
+	if (_vm->_game.version == 0)
+		return Actor::remapDirection(dir, is_walking);
+
+	static const byte remapTable1[] = {
+		0x04, 0x01, 0x02, 0x00, 0x01, 0x02, 0x03, 0x00,
+		0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00,
+		0x07, 0x00, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00,
+		0x05, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x00
+	};
+
+	static const byte remapTable2[] = {
+		0x00, 0x01, 0x03, 0x02, 0x03, 0x00, 0x02, 0x00,
+		0x00, 0x01, 0x03, 0x02, 0x01, 0x03, 0x01, 0x02,
+		0x00, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x02,
+		0x00, 0x01, 0x03, 0x02, 0x03, 0x03, 0x01, 0x01
+	};
+
+	static const byte remapTable3[] = {
+		0x00, 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x00,
+		0x01, 0x01, 0x02, 0x00, 0x01, 0x03, 0x02, 0x00,
+		0x02, 0x01, 0x02, 0x00, 0x01, 0x03, 0x02, 0x00,
+		0x03, 0x00, 0x03, 0x00, 0x01, 0x03, 0x02, 0x00
+	};
+
+	if (_moving & ~MF_TURN)
+		_targetFacing = oldDirToNewDir(remapTable2[newDirToOldDir(dir) * 8 + remapTable1[_walkdata.facing * 8 + (_vm->getBoxFlags(_walkbox) & 7)]]);
+	else 
+		_targetFacing = oldDirToNewDir(remapTable3[newDirToOldDir(dir) * 8 + (_vm->getBoxFlags(_walkbox) & 7)]);
+
+	return _targetFacing | 0x400;
+}
+
 int Actor::updateActorDirection(bool is_walking) {
 	static const uint8 actorTurnInterpolateTable[] = { 0, 2, 2, 3, 2, 1, 2, 3, 0, 1, 2, 1, 0, 1, 0, 3 };
 
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index d91f710271d..8b44ad54c2f 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -223,8 +223,8 @@ public:
 	void setActorWalkSpeed(uint newSpeedX, uint newSpeedY);
 protected:
 	virtual int calcMovementFactor(const Common::Point& next);
-	int actorWalkStep();
-	int remapDirection(int dir, bool is_walking);
+	virtual int actorWalkStep();
+	virtual int remapDirection(int dir, bool is_walking);
 	virtual void setupActorScale();
 
 	void setBox(int box);
@@ -362,13 +362,12 @@ public:
 
 protected:
 	int calcMovementFactor(const Common::Point& next) override;
-	int actorWalkStep();
-
 	void setupActorScale() override;
 	void findPathTowardsOld(byte box, byte box2, byte box3, Common::Point &p2, Common::Point &p3);
-
+	uint _stepThreshold;
 private:
-	uint _stepX, _stepThreshold;
+	virtual int actorWalkStep();
+	uint _stepX;
 	const int _facingXYratio;
 };
 
@@ -383,6 +382,9 @@ public:
 protected:
 	bool isPlayer() override;
 	void prepareDrawActorCostume(BaseCostumeRenderer *bcr) override;
+private:
+	int actorWalkStep() override;
+	int remapDirection(int dir, bool is_walking) override;
 };
 
 class Actor_v7 final : public Actor {
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index ed863de4eed..c182b9d5da3 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1760,6 +1760,13 @@ void ScummEngine::resetScumm() {
 	setShake(0);
 	_cursor.animate = 1;
 
+	if (_actors) {
+		for (i = 0; i < _numActors; ++i)
+			delete _actors[i];
+		delete[] _actors;
+	}
+	delete[] _sortedActors;
+
 	// Allocate and Initialize actors
 	Actor::kInvalidBox = ((_game.features & GF_SMALL_HEADER) ? kOldInvalidBox : kNewInvalidBox);
 	_actors = new Actor * [_numActors];




More information about the Scummvm-git-logs mailing list