diff options
author | Kirben | 2014-12-07 15:09:36 +1100 |
---|---|---|
committer | Kirben | 2014-12-07 15:09:36 +1100 |
commit | dcd0f597e6026e248ff6e2db0224f3f60626cdca (patch) | |
tree | f616b8ed6ae0b0ce56f7c81dd65ad4af84754ded /engines/scumm | |
parent | d8af639dfcbdae3c99f72c4c4ec4f07410d5915c (diff) | |
parent | 4b1b9ec66f5889fd20d88f8f7f565e8448ac8389 (diff) | |
download | scummvm-rg350-dcd0f597e6026e248ff6e2db0224f3f60626cdca.tar.gz scummvm-rg350-dcd0f597e6026e248ff6e2db0224f3f60626cdca.tar.bz2 scummvm-rg350-dcd0f597e6026e248ff6e2db0224f3f60626cdca.zip |
Merge pull request #539 from segrax/master
SCUMM: Maniac V0: Original Walk Code Implementation
Diffstat (limited to 'engines/scumm')
-rw-r--r-- | engines/scumm/actor.cpp | 589 | ||||
-rw-r--r-- | engines/scumm/actor.h | 49 | ||||
-rw-r--r-- | engines/scumm/boxes.cpp | 24 | ||||
-rw-r--r-- | engines/scumm/saveload.h | 2 | ||||
-rw-r--r-- | engines/scumm/script.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/script_v0.cpp | 7 | ||||
-rw-r--r-- | engines/scumm/script_v5.cpp | 4 | ||||
-rw-r--r-- | engines/scumm/scumm_v0.h | 4 | ||||
-rw-r--r-- | engines/scumm/verbs.cpp | 2 |
9 files changed, 562 insertions, 125 deletions
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 116a953b0b..90ee5bf368 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -33,6 +33,7 @@ #include "scumm/resource.h" #include "scumm/saveload.h" #include "scumm/scumm_v7.h" +#include "scumm/scumm_v0.h" #include "scumm/he/sound_he.h" #include "scumm/he/sprite_he.h" #include "scumm/usage_bits.h" @@ -50,6 +51,12 @@ static const byte v0ActorTalkArray[0x19] = { 0xC0, 0xC0, 0x00, 0x06, 0x06 }; +static const byte v0WalkboxSlantedModifier[0x16] = { + 0x00,0x01,0x02,0x03,0x03,0x04,0x05,0x06, + 0x06,0x07,0x08,0x09,0x09,0x0A,0x0B, + 0x0C,0x0C,0x0D,0x0E,0x0F,0x10,0x10 +}; + Actor::Actor(ScummEngine *scumm, int id) : _vm(scumm), _number(id) { assert(_vm != 0); @@ -182,6 +189,20 @@ void Actor_v0::initActor(int mode) { _costCommand = 0xFF; _miscflags = 0; _speaking = 0; + + _walkCountModulo = 0; + _newWalkBoxEntered = false; + _walkDirX = 0; + _walkDirY = 0; + _walkYCountGreaterThanXCount = 0; + _walkXCount = 0; + _walkXCountInc = 0; + _walkYCount = 0; + _walkYCountInc = 0; + _walkMaxXYCountInc = 0; + + _tmp_WalkBox = 0; + _tmp_NewWalkBoxEntered = 0; _animFrameRepeat = 0; for (int i = 0; i < 8; ++i) { @@ -249,9 +270,12 @@ void Actor::stopActorMoving() { if (_walkScript) _vm->stopScript(_walkScript); - _moving = 0; - if (_vm->_game.version == 0) + if (_vm->_game.version == 0) { + _moving = 2; setDirection(_facing); + } else { + _moving = 0; + } } void Actor::setActorWalkSpeed(uint newSpeedX, uint newSpeedY) { @@ -339,9 +363,6 @@ int Actor::actorWalkStep() { int distX, distY; int nextFacing; - if (_vm->_game.version == 0) - ((Actor_v0 *)this)->_animFrameRepeat = -1; - _needRedraw = true; nextFacing = updateActorDirection(true); @@ -350,10 +371,6 @@ int Actor::actorWalkStep() { startWalkAnim(1, nextFacing); } _moving |= MF_IN_LEG; - - // V0: Don't move during the turn - if (_vm->_game.version == 0) - return 0; } if (_walkbox != _walkdata.curbox && _vm->checkXYInBoxBounds(_walkdata.curbox, _pos.x, _pos.y)) { @@ -389,12 +406,113 @@ int Actor::actorWalkStep() { return 0; } - if (_vm->_game.version == 0) - ((Actor_v0 *)this)->animateActor(newDirToOldDir(_facing)); - return 1; } +bool Actor_v0::calcWalkDistances() { + _walkDirX = 0; + _walkDirY = 0; + _walkYCountGreaterThanXCount = 0; + uint16 A = 0; + + if (_CurrentWalkTo.x >= _tmp_Dest.x ) { + A = _CurrentWalkTo.x - _tmp_Dest.x; + _walkDirX = 1; + } else { + A = _tmp_Dest.x - _CurrentWalkTo.x; + } + + _walkXCountInc = A; + + if (_CurrentWalkTo.y >= _tmp_Dest.y ) { + A = _CurrentWalkTo.y - _tmp_Dest.y; + _walkDirY = 1; + } else { + A = _tmp_Dest.y - _CurrentWalkTo.y; + } + + _walkYCountInc = A; + if ( !_walkXCountInc && !_walkYCountInc ) + return true; + + if( _walkXCountInc <= _walkYCountInc ) + _walkYCountGreaterThanXCount = 1; + + // 2FCC + A = _walkXCountInc; + if( A <= _walkYCountInc ) + A = _walkYCountInc; + + _walkMaxXYCountInc = A; + _walkXCount = _walkXCountInc; + _walkYCount = _walkYCountInc; + _walkCountModulo = _walkMaxXYCountInc; + + return false; +} + +byte Actor_v0::actorWalkX() { + byte A = _walkXCount; + A += _walkXCountInc; + if (A >= _walkCountModulo) { + if (!_walkDirX ) { + _tmp_Dest.x--; + } else { + _tmp_Dest.x++; + } + + A -= _walkCountModulo; + } + // 2EAC + _walkXCount = A; + setTmpFromActor(); + if (updateWalkbox() == kInvalidBox) { + // 2EB9 + setActorFromTmp(); + + return 3; + } + // 2EBF + if (_tmp_Dest.x == _CurrentWalkTo.x) + return 1; + + return 0; +} + +byte Actor_v0::actorWalkY() { + byte A = _walkYCount; + A += _walkYCountInc; + if (A >= _walkCountModulo) { + if (!_walkDirY ) { + _tmp_Dest.y--; + } else { + _tmp_Dest.y++; + } + + A -= _walkCountModulo; + } + // 2EEB + _walkYCount = A; + setTmpFromActor(); + if (updateWalkbox() == kInvalidBox) { + // 2EF8 + setActorFromTmp(); + return 4; + } + // 2EFE + if (_walkYCountInc != 0) { + if (_walkYCountInc == 0xFF) { + setActorFromTmp(); + return 4; + } + } + // 2F0D + if (_CurrentWalkTo.y == _tmp_Dest.y) + return 1; + + return 0; +} + void Actor::startWalkActor(int destX, int destY, int dir) { AdjustBoxResult abr; @@ -447,10 +565,14 @@ void Actor::startWalkActor(int destX, int destY, int dir) { _walkdata.dest.y = abr.y; _walkdata.destbox = abr.box; _walkdata.destdir = dir; - _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG; _walkdata.point3.x = 32000; - _walkdata.curbox = _walkbox; + + if(_vm->_game.version == 0 ) { + ((Actor_v0*)this)->_newWalkBoxEntered = true; + } else { + _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG; + } } void Actor::startWalkAnim(int cmd, int angle) { @@ -567,88 +689,206 @@ void Actor::walkActor() { calcMovementFactor(_walkdata.dest); } -bool Actor_v2::checkWalkboxesHaveDirectPath(Common::Point &foundPath) { - // only MM v0 supports walking in direct line between walkboxes. - // MM v1 already does not support it anymore. - return false; -} +void Actor_v0::walkActor() { + actorSetWalkTo(); -bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, - const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result) -{ - const Common::Point v1 = line1End - line1Start; // line1(n1) = line1Start + n1 * v1 - const Common::Point v2 = line2End - line2Start; // line2(n2) = line2Start + n2 * v2 + _needRedraw = true; + if (_NewWalkTo != _CurrentWalkTo) { + _CurrentWalkTo = _NewWalkTo; - double det = v2.x * v1.y - v1.x * v2.y; - if (det == 0) - return false; +L2A33:; + _moving &= 0xF0; + _tmp_Dest = _pos; - double n1 = ((double)v2.x * (line2Start.y - line1Start.y) - - (double)v2.y * (line2Start.x - line1Start.x)) / det; - double n2 = ((double)v1.x * (line2Start.y - line1Start.y) - - (double)v1.y * (line2Start.x - line1Start.x)) / det; + byte tmp = calcWalkDistances(); + _moving &= 0xF0; + _moving |= tmp; - // both coefficients have to be in [0, 1], otherwise the intersection is - // not inside of at least one of the two line segments - if (n1 < 0.0 || n1 > 1.0 || n2 < 0.0 || n2 > 1.0) - return false; + if (!_walkYCountGreaterThanXCount) { + if (_walkDirX) { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*1, V12_Y_MULTIPLIER*0, false); + } else { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*-1, V12_Y_MULTIPLIER*0, false); + } + } else { + if (_walkDirY) { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*1, false); + } else { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*-1, false); + } + } - result.x = line1Start.x + (int)(n1 * v1.x); - result.y = line1Start.y + (int)(n1 * v1.y); - return true; -} + directionUpdate(); + + if (_moving & 0x80) + return; -/* - * MM v0 allows the actor to walk in a direct line between boxes to the target - * if actor and target share a horizontal or vertical corridor. - * If such a corridor is found the actor is not forced to go horizontally or - * vertically from one box to the next but can also walk diagonally. - * - * Note: the original v0 interpreter sets the target destination for diagonal - * walking only once and then rechecks whenever the actor reaches a new box if the - * walk destination is still suitable for the current box. - * ScummVM does not perform such a check, so it is possible to leave the walkboxes - * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water) - * or the medical room (actor walks over examination table). - * To solve this we intersect the new walk destination with the actor's walkbox borders, - * so a recheck is done when the actor leaves his box. This is done by the - * intersectLineSegments() routine calls. - */ -bool Actor_v0::checkWalkboxesHaveDirectPath(Common::Point &foundPath) { - BoxCoords boxCoords = _vm->getBoxCoordinates(_walkbox); - BoxCoords curBoxCoords = _vm->getBoxCoordinates(_walkdata.curbox); - - // check if next walkbox is left or right to actor's box - if (boxCoords.ll.x > curBoxCoords.lr.x || boxCoords.lr.x < curBoxCoords.ll.x) { - // determine horizontal corridor gates - int gateUpper = MAX(boxCoords.ul.y, curBoxCoords.ul.y); - int gateLower = MIN(boxCoords.ll.y, curBoxCoords.ll.y); - - // check if actor and target are in the same horizontal corridor between the boxes - if ((_pos.y >= gateUpper && _pos.y <= gateLower) && - (_walkdata.dest.y >= gateUpper && _walkdata.dest.y <= gateLower)) { - if (boxCoords.ll.x > curBoxCoords.lr.x) // next box is left - return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ll, boxCoords.ul, foundPath); - else // next box is right - return intersectLineSegments(_pos, _walkdata.dest, boxCoords.lr, boxCoords.ur, foundPath); - } - // check if next walkbox is above or below actor's box - } else if (boxCoords.ul.y > curBoxCoords.ll.y || boxCoords.ll.y < curBoxCoords.ul.y) { - // determine vertical corridor gates - int gateLeft = MAX(boxCoords.ll.x, curBoxCoords.ll.x); - int gateRight = MIN(boxCoords.lr.x, curBoxCoords.lr.x); - - // check if actor and target are in the same vertical corridor between the boxes - if ((_pos.x >= gateLeft && _pos.x <= gateRight) && - (_walkdata.dest.x >= gateLeft && _walkdata.dest.x <= gateRight)) { - if (boxCoords.ul.y > curBoxCoords.ll.y) // next box is above - return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ul, boxCoords.ur, foundPath); - else // next box is below - return intersectLineSegments(_pos, _walkdata.dest, boxCoords.ll, boxCoords.lr, foundPath); + animateActor(newDirToOldDir(_facing)); + + } else { + // 2A0A + if ((_moving & 0x7F) != 1) { + + if (_NewWalkTo == _pos) + return; } } - return false; + // 2A9A + if (_moving == 2) + return; + + if ((_moving & 0x0F) == 1) + return stopActorMoving(); + + // 2AAD + if (_moving & 0x80) { + directionUpdate(); + + if (_moving & 0x80) + return; + + animateActor(newDirToOldDir(_facing)); + } + + if ((_moving & 0x0F) == 3 ) { +L2C36:; + setTmpFromActor(); + + if (!_walkDirX) { + _pos.x--; + } else { + _pos.x++; + } + + // 2C51 + if (updateWalkbox() != kInvalidBox) { + + setActorFromTmp(); + goto L2A33; + } + + setActorFromTmp(); + + if (_CurrentWalkTo.y == _tmp_Dest.y) { + stopActorMoving(); + return; + } + + if (!_walkDirY) { + _tmp_Dest.y--; + } else { + _tmp_Dest.y++; + } + + setTmpFromActor(); + + byte A = updateWalkbox(); + if (A == 0xFF) { + setActorFromTmp(); + stopActorMoving(); + return; + } + // 2C98: Yes, an exact copy of what just occured.. the original does this, so im doing it... + // Just to keep me sane when going over it :) + if (A == 0xFF) { + setActorFromTmp(); + stopActorMoving(); + return; + } + return; + } + + // 2ADA + if ((_moving & 0x0F) == 4) { +L2CA3:; + setTmpFromActor(); + + if (!_walkDirY) { + _pos.y--; + } else { + _pos.y++; + } + if (updateWalkbox() == kInvalidBox) { + // 2CC7 + setActorFromTmp(); + if( _CurrentWalkTo.x == _tmp_Dest.x) { + stopActorMoving(); + return; + } + + if (!_walkDirX) { + _tmp_Dest.x--; + } else { + _tmp_Dest.x++; + } + setTmpFromActor(); + + if (updateWalkbox() == kInvalidBox) { + setActorFromTmp(); + stopActorMoving(); + } + + return; + } else { + setActorFromTmp(); + goto L2A33; + } + } + + if ((_moving & 0x0F) == 0) { + // 2AE8 + byte A = actorWalkX(); + + if (A == 1) { + A = actorWalkY(); + if (A == 1) { + _moving &= 0xF0; + _moving |= A; + } else { + if (A == 4) + stopActorMoving(); + } + + return; + + } else { + // 2B0C + if (A == 3) { + _moving &= 0xF0; + _moving |= A; + + if (_walkDirY) { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*1, false); + } else { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*0, V12_Y_MULTIPLIER*-1, false); + } + + directionUpdate(); + animateActor(newDirToOldDir(_facing)); + goto L2C36; + + } else { + // 2B39 + A = actorWalkY(); + if (A != 4) + return; + + _moving &= 0xF0; + _moving |= A; + + if (_walkDirX) { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*1, V12_Y_MULTIPLIER*0, false); + } else { + _targetFacing = getAngleFromPos(V12_X_MULTIPLIER*-1, V12_Y_MULTIPLIER*0, false); + } + + directionUpdate(); + animateActor(newDirToOldDir(_facing)); + goto L2CA3; + } + } + } } void Actor_v2::walkActor() { @@ -697,10 +937,8 @@ void Actor_v2::walkActor() { _walkdata.curbox = next_box; - if (!checkWalkboxesHaveDirectPath(foundPath)) { - 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); - } + 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); } calcMovementFactor(foundPath); } @@ -985,18 +1223,16 @@ void Actor_v0::setDirection(int direction) { break; case 2: - res = 6; // Face Away + res = 6; // Face Camera break; default: - res = 7; // Face Camera + res = 7; // Face Away break; } _animFrameRepeat = -1; animateActor(res); - if (_moving) - animateCostume(); } void Actor::faceToObject(int obj) { @@ -1017,8 +1253,14 @@ void Actor::turnToDirection(int newdir) { return; if (_vm->_game.version <= 6) { - _moving = MF_TURN; _targetFacing = newdir; + + if (_vm->_game.version == 0 ) { + setDirection( newdir ); + return; + } + _moving = MF_TURN; + } else { _moving &= ~MF_TURN; if (newdir != _facing) { @@ -1085,8 +1327,14 @@ void Actor::putActor(int dstX, int dstY, int newRoom) { } // V0 always sets the actor to face the camera upon entering a room - if (_vm->_game.version == 0) + if (_vm->_game.version == 0) { + _walkdata.dest = _pos; + + ((Actor_v0*)this)->_newWalkBoxEntered = true; + ((Actor_v0*)this)->_CurrentWalkTo = _pos; + setDirection(oldDirToNewDir(2)); + } } static bool inBoxQuickReject(const BoxCoords &box, int x, int y, int threshold) { @@ -1200,6 +1448,59 @@ static int checkXYInBoxBounds(int boxnum, int x, int y, int &destX, int &destY) return dist; } +AdjustBoxResult Actor_v0::adjustPosInBorderWalkbox(AdjustBoxResult box) { + AdjustBoxResult Result = box; + BoxCoords BoxCoord = _vm->getBoxCoordinates(box.box); + + byte boxMask = _vm->getMaskFromBox(box.box); + if (!(boxMask & 0x80)) + return Result; + + char A; + boxMask &= 0x7C; + if (boxMask == 0x0C) + A = 2; + else { + if (boxMask != 0x08) + return Result; + + A = 1; + } + + // 1BC6 + byte Modifier = box.y - BoxCoord.ul.y; + assert(Modifier < 0x16); + + if (A == 1) { + // 1BCF + A = BoxCoord.ur.x - v0WalkboxSlantedModifier[ Modifier ]; + if (A < box.x) + return box; + + if (A < 0xA0 || A == 0xA0) + A = 0; + + Result.x = A; + } else { + // 1BED + A = BoxCoord.ul.x + v0WalkboxSlantedModifier[ Modifier ]; + + if (A < box.x || A == box.x) + Result.x = A; + } + + return Result; +} + +AdjustBoxResult Actor_v0::adjustXYToBeInBox(int dstX, int dstY) { + AdjustBoxResult Result = Actor_v2::adjustXYToBeInBox(dstX, dstY); + + if( Result.box == kInvalidBox ) + return Result; + + return adjustPosInBorderWalkbox(Result); +} + AdjustBoxResult Actor_v2::adjustXYToBeInBox(const int dstX, const int dstY) { AdjustBoxResult abr; @@ -1410,6 +1711,7 @@ void Actor::showActor() { Actor_v0 *a = ((Actor_v0 *)this); a->_costCommand = a->_costCommandNew = 0xFF; + _walkdata.dest = a->_CurrentWalkTo; for (int i = 0; i < 8; ++i) { a->_limbFrameRepeat[i] = 0; @@ -1642,7 +1944,7 @@ void ScummEngine::processActors() { continue; // Sound - if (a0->_moving && _currentRoom != 1 && _currentRoom != 44) { + if (a0->_moving != 2 && _currentRoom != 1 && _currentRoom != 44) { if (a0->_cost.soundPos == 0) a0->_cost.soundCounter++; @@ -1659,8 +1961,17 @@ void ScummEngine::processActors() { // would hence cause regressions. See also the other big // comment further up in this method for some details. if (a->_costume) { - a->drawActorCostume(); - a->animateCostume(); + + // Unfortunately in V0, the 'animateCostume' call happens right after the call to 'walkActor' (which is before drawing the actor)... + // doing it the other way with V0, causes animation glitches (when beginnning to walk, as the costume hasnt been updated). + // Updating the costume directly after 'walkActor' and again, after drawing... causes frame skipping + if (_game.version == 0) { + a->animateCostume(); + a->drawActorCostume(); + } else { + a->drawActorCostume(); + a->animateCostume(); + } } } } @@ -2897,6 +3208,70 @@ void Actor_v0::animateActor(int anim) { } } +byte Actor_v0::updateWalkbox() { + if( _vm->checkXYInBoxBounds( _walkbox, _pos.x, _pos.y ) ) + return 0; + + int numBoxes = _vm->getNumBoxes() - 1; + for (int i = 0; i <= numBoxes; i++) { + if (_vm->checkXYInBoxBounds( i, _pos.x, _pos.y ) == true ) { + if (_walkdata.curbox == i) { + setBox(i); + directionUpdate(); + + _newWalkBoxEntered = true; + return i; + } + } + } + + return kInvalidBox; +} + +void Actor_v0::directionUpdate() { + + int nextFacing = updateActorDirection(true); + if (_facing != nextFacing) { + // 2A89 + setDirection(nextFacing); + + // Still need to turn? + if (_facing != _targetFacing) { + _moving |= 0x80; + return; + } + } + + _moving &= ~0x80; +} + +void Actor_v0::setTmpFromActor() { + _tmp_Pos = _pos; + _pos = _tmp_Dest; + _tmp_WalkBox = _walkbox; + _tmp_NewWalkBoxEntered = _newWalkBoxEntered; +} + +void Actor_v0::setActorFromTmp() { + _pos = _tmp_Pos; + _tmp_Dest = _tmp_Pos; + _walkbox = _tmp_WalkBox; + _newWalkBoxEntered = _tmp_NewWalkBoxEntered; +} + +void Actor_v0::actorSetWalkTo() { + + if (_newWalkBoxEntered == false) + return; + + _newWalkBoxEntered = false; + + int nextBox = ((ScummEngine_v0*)_vm)->walkboxFindTarget(this, _walkdata.destbox, _walkdata.dest); + if (nextBox != kInvalidBox) { + _walkdata.curbox = nextBox; + } +} + void Actor_v0::saveLoadWithSerializer(Serializer *ser) { Actor::saveLoadWithSerializer(ser); @@ -2910,6 +3285,20 @@ void Actor_v0::saveLoadWithSerializer(Serializer *ser) { MKLINE(Actor_v0, _animFrameRepeat, sleByte, VER(89)), MKARRAY(Actor_v0, _limbFrameRepeatNew[0], sleInt8, 8, VER(89)), MKARRAY(Actor_v0, _limbFrameRepeat[0], sleInt8, 8, VER(90)), + MKLINE(Actor_v0, _CurrentWalkTo.x, sleInt16, VER(97)), + MKLINE(Actor_v0, _CurrentWalkTo.y, sleInt16, VER(97)), + MKLINE(Actor_v0, _NewWalkTo.x, sleInt16, VER(97)), + MKLINE(Actor_v0, _NewWalkTo.y, sleInt16, VER(97)), + MKLINE(Actor_v0, _walkCountModulo, sleInt8, VER(97)), + MKLINE(Actor_v0, _newWalkBoxEntered, sleByte, VER(97)), + MKLINE(Actor_v0, _walkDirX, sleByte, VER(97)), + MKLINE(Actor_v0, _walkDirY, sleByte, VER(97)), + MKLINE(Actor_v0, _walkYCountGreaterThanXCount, sleByte, VER(97)), + MKLINE(Actor_v0, _walkXCount, sleByte, VER(97)), + MKLINE(Actor_v0, _walkXCountInc, sleByte, VER(97)), + MKLINE(Actor_v0, _walkYCount, sleByte, VER(97)), + MKLINE(Actor_v0, _walkYCountInc, sleByte, VER(97)), + MKLINE(Actor_v0, _walkMaxXYCountInc, sleByte, VER(97)), MKEND() }; diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index 46dc7d0295..c1a3f23318 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -333,7 +333,6 @@ public: protected: virtual bool isPlayer(); virtual void prepareDrawActorCostume(BaseCostumeRenderer *bcr); - virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath); }; enum ActorV0MiscFlags { @@ -349,11 +348,32 @@ enum ActorV0MiscFlags { class Actor_v0 : public Actor_v2 { public: + Common::Point _CurrentWalkTo, _NewWalkTo; + byte _costCommandNew; byte _costCommand; byte _miscflags; byte _speaking; + byte _walkCountModulo; + bool _newWalkBoxEntered; + + byte _walkDirX; + byte _walkDirY; + + byte _walkYCountGreaterThanXCount; + byte _walkXCount; + byte _walkXCountInc; + byte _walkYCount; + byte _walkYCountInc; + + byte _walkMaxXYCountInc; + + Common::Point _tmp_Pos; + Common::Point _tmp_Dest; + byte _tmp_WalkBox; + bool _tmp_NewWalkBoxEntered; + int8 _animFrameRepeat; int8 _limbFrameRepeatNew[8]; int8 _limbFrameRepeat[8]; @@ -363,23 +383,32 @@ public: public: Actor_v0(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {} - virtual void initActor(int mode); - virtual void animateActor(int anim); - virtual void animateCostume(); + void initActor(int mode); + void animateActor(int anim); + void animateCostume(); void limbFrameCheck(int limb); + void directionUpdate(); void speakCheck(); - virtual void setDirection(int direction); + void setDirection(int direction); void startAnimActor(int f); + bool calcWalkDistances(); + void walkActor(); + void actorSetWalkTo(); + byte actorWalkX(); + byte actorWalkY(); + byte updateWalkbox(); + + AdjustBoxResult adjustXYToBeInBox(int dstX, int dstY); + AdjustBoxResult adjustPosInBorderWalkbox(AdjustBoxResult box); + + void setTmpFromActor(); + void setActorFromTmp(); + // Used by the save/load system: virtual void saveLoadWithSerializer(Serializer *ser); - -protected: - bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, - const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result); - virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath); }; diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp index 70c8f2e032..087d8425ac 100644 --- a/engines/scumm/boxes.cpp +++ b/engines/scumm/boxes.cpp @@ -1158,6 +1158,30 @@ bool ScummEngine::areBoxesNeighbors(int box1nr, int box2nr) { return false; } +byte ScummEngine_v0::walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest) { + Actor_v0 *Actor = (Actor_v0*)a; + + byte nextBox = getNextBox(a->_walkbox, destbox); + + if (nextBox != 0xFF && nextBox == destbox && areBoxesNeighbors(a->_walkbox, nextBox)) { + + Actor->_NewWalkTo = walkdest; + return nextBox; + } + + if (nextBox != 0xFF && nextBox != a->_walkbox) { + + getClosestPtOnBox(getBoxCoordinates(nextBox), a->getPos().x, a->getPos().y, Actor->_NewWalkTo.x, Actor->_NewWalkTo.y); + + } else { + if (walkdest.x == -1) + Actor->_NewWalkTo = Actor->_CurrentWalkTo; + else + Actor->_NewWalkTo = walkdest; + } + return nextBox; +} + bool ScummEngine_v0::areBoxesNeighbors(int box1nr, int box2nr) { int i; const int numOfBoxes = getNumBoxes(); diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index 01ed21ece5..753287e217 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -47,7 +47,7 @@ namespace Scumm { * only saves/loads those which are valid for the version of the savegame * which is being loaded/saved currently. */ -#define CURRENT_VER 96 +#define CURRENT_VER 97 /** * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index 2fe5333bfc..c9b37d43b1 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -1164,8 +1164,10 @@ void ScummEngine_v0::walkToActorOrObject(int object) { VAR(7) = y; // actor must not move if frozen - if (a->_miscflags & kActorMiscFlagFreeze) + if (a->_miscflags & kActorMiscFlagFreeze) { a->stopActorMoving(); + a->_newWalkBoxEntered = false; + } } bool ScummEngine_v0::checkPendingWalkAction() { @@ -1179,7 +1181,7 @@ bool ScummEngine_v0::checkPendingWalkAction() { Actor_v0 *a = (Actor_v0 *)derefActor(actor, "checkPendingWalkAction"); // wait until walking or turning action is finished - if (a->_moving) + if (a->_moving != 2) return true; // after walking and turning finally execute the script diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp index af39fdaad8..90291535fd 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -707,17 +707,14 @@ void ScummEngine_v0::o_animateActor() { } a->animateActor(anim); - a->animateCostume(); } void ScummEngine_v0::o_getActorMoving() { getResultPos(); int act = getVarOrDirectByte(PARAM_1); Actor *a = derefActor(act, "o_getActorMoving"); - if (a->_moving) - setResult(1); - else - setResult(2); + + setResult(a->_moving); } void ScummEngine_v0::o_putActorAtObject() { diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index 91afa859a9..4a53ca3fed 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -2497,10 +2497,6 @@ void ScummEngine_v5::walkActorToActor(int actor, int toActor, int dist) { y = abr.y; } a->startWalkActor(x, y, -1); - - // WORKAROUND: See bug #2971126 for details on why this is here. - if (_game.version == 0) - o5_breakHere(); } void ScummEngine_v5::o5_walkActorToActor() { diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h index 80d047ab9f..83e0e32e15 100644 --- a/engines/scumm/scumm_v0.h +++ b/engines/scumm/scumm_v0.h @@ -67,6 +67,8 @@ public: virtual void resetScumm(); + byte walkboxFindTarget(Actor *a, int destbox, Common::Point walkdest); + protected: virtual void resetRoomObject(ObjectData *od, const byte *room, const byte *searchptr = NULL); @@ -116,7 +118,7 @@ protected: void resetSentence(); - virtual bool areBoxesNeighbors(int box1nr, int box2nr); + bool areBoxesNeighbors(int box1nr, int box2nr); bool ifEqualActiveObject2Common(bool checkType); diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index fdb98a8019..bf0a693467 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -708,7 +708,6 @@ void ScummEngine_v0::verbExec() { Actor_v0 *a = (Actor_v0 *)derefActor(VAR(VAR_EGO), "verbExec"); int x = _virtualMouse.x / V12_X_MULTIPLIER; int y = _virtualMouse.y / V12_Y_MULTIPLIER; - //actorSetPosInBox(); // 0xB31 VAR(6) = x; @@ -717,7 +716,6 @@ void ScummEngine_v0::verbExec() { if (a->_miscflags & kActorMiscFlagFreeze) return; - a->stopActorMoving(); a->startWalkActor(VAR(6), VAR(7), -1); } |