[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