From 2dbd99d57264bab012cebd064eadfc34050832b1 Mon Sep 17 00:00:00 2001 From: Robert Crossfield Date: Fri, 28 Nov 2014 22:24:45 +1100 Subject: SCUMM: Maniac V0: Implement the original Walk Code (to fix some anim glitches), fix opcode to use _moving correctly (as V0 is different) --- engines/scumm/actor.cpp | 440 +++++++++++++++++++++++++++++++++++++++++++- engines/scumm/actor.h | 40 +++- engines/scumm/script.cpp | 2 +- engines/scumm/script_v0.cpp | 12 +- engines/scumm/verbs.cpp | 1 - 5 files changed, 473 insertions(+), 22 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 116a953b0b..1ea1f6eb54 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -250,8 +250,11 @@ void Actor::stopActorMoving() { _vm->stopScript(_walkScript); _moving = 0; - if (_vm->_game.version == 0) + + if (_vm->_game.version == 0) { + _moving = 2; setDirection(_facing); + } } void Actor::setActorWalkSpeed(uint newSpeedX, uint newSpeedY) { @@ -447,7 +450,11 @@ 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; + if(_vm->_game.version != 0 ) { + _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG; + } else { + ((Actor_v0*)this)->unk_FDE1 = 1; + } _walkdata.point3.x = 32000; _walkdata.curbox = _walkbox; @@ -651,6 +658,403 @@ bool Actor_v0::checkWalkboxesHaveDirectPath(Common::Point &foundPath) { return false; } +bool Actor_v0::sub_2F6F() { + _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::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); + + unk_FDE1 = 1; + return i; + } + } + } + + return 0xFF; +} + +void Actor_v0::setTmpFromActor() { + _tmp_Pos = _pos; + _pos = _tmp_Dest; + _tmp_WalkBox = _walkbox; + _tmp_CB5F = unk_FDE1; +} + +void Actor_v0::setActorFromTmp() { + _pos = _tmp_Pos; + _tmp_Dest = _tmp_Pos; + _walkbox = _tmp_WalkBox; + unk_FDE1 = _tmp_CB5F; +} + +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() == 0xFF ) { + // 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() == 0xFF) { + // 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; +} + +byte Actor_v0::walkboxFindTarget() { + return 0xff; +} + +void Actor_v0::actorSetWalkTo() { + + if (unk_FDE1 == 0 ) + return; + + unk_FDE1 = 0; + byte nextBox = _vm->getNextBox(_walkbox, _walkdata.destbox); + + if (nextBox != 0xFF && nextBox != _walkbox ) { + Common::Point tmp; + _walkdata.curbox = nextBox; + + getClosestPtOnBox(_vm->getBoxCoordinates(nextBox), _pos.x, _pos.y, _NewWalkTo.x, _NewWalkTo.y); + //getClosestPtOnBox(_vm->getBoxCoordinates(_walkbox), tmp.x, tmp.y, _NewWalkTo.x, _NewWalkTo.y); + + + } else { + if( _walkdata.dest.x == -1 ) + _NewWalkTo = _CurrentWalkTo; + else + _NewWalkTo = _walkdata.dest; + } +} + +void Actor_v0::walkActor() { + actorSetWalkTo(); + + _needRedraw = true; + if (_NewWalkTo != _CurrentWalkTo) { + + // 2A27 + _CurrentWalkTo = _NewWalkTo; + +loc_2A33:; + _moving &= 0xF0; + _tmp_Dest = _pos; + + byte tmp = sub_2F6F(); + _moving &= 0xF0; + _moving |= tmp; + + 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); + } + } + + directionUpdate(); + + if (_moving & 0x80 ) + return; + + animateActor(newDirToOldDir(_facing)); + + } else { + // 2A0A + if ((_moving & 0x7F) != 1) { + + if (_NewWalkTo == _pos) { + return; + } + } + } + + + // 2A9A + if (_moving == 2 ) + return; + + if ((_moving & 0x0F) == 1 ) + return stopActorMoving(); + + // 2AAD + if (_moving & 0x80) { + directionUpdate(); + + if ((_moving & 0x80) ) + return; + + // 2AC2 + animateActor(newDirToOldDir(_facing)); + } + + // 2ACE + if ((_moving & 0x0F) == 3 ) { +loc_2C36:; + // 2C36 + setTmpFromActor(); + + if (!_walkDirX ) { + _pos.x--; + } else { + _pos.x++; + } + + // 2C51 + if (updateWalkbox() != 0xFF) { + //2C66 + setActorFromTmp(); + goto loc_2A33; + } + + // 2C6C + setActorFromTmp(); + + if (_CurrentWalkTo.y == _tmp_Dest.y) { + stopActorMoving(); + return; + } + + if (!_walkDirY) { + _tmp_Dest.y--; + } else { + _tmp_Dest.y++; + } + setTmpFromActor(); + //2C8B + 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 ) { + // 2CA3 +loc_2CA3:; + setTmpFromActor(); + + if (!_walkDirY) { + _pos.y--; + } else { + _pos.y++; + } + if (updateWalkbox() == 0xFF ) { + // 2CC7 + setActorFromTmp(); + if( _CurrentWalkTo.x == _tmp_Dest.x ) { + stopActorMoving(); + return; + } + // 2CD5 + if (!_walkDirX ) { + _tmp_Dest.x--; + } else { + _tmp_Dest.x++; + } + setTmpFromActor(); + + if (updateWalkbox() == 0xFF ) { + setActorFromTmp(); + stopActorMoving(); + } + + return; + } else { + setActorFromTmp(); + goto loc_2A33; + } + } + + if ((_moving & 0x0F) == 0 ) { + // 2AE8 + byte A = actorWalkX(); + + if( A == 1 ) { + A = actorWalkY(); + if( A == 1 ) { + // 2AF6 + _moving &= 0xF0; + _moving |= A; + } else { + // 2B04 + 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 loc_2C36; + + } else { + // 2B39 + A = actorWalkY(); + if (A != 4 ) + return; + + // 2B46 + _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 loc_2CA3; + } + } + } +} + +void Actor_v0::directionUpdate() { + + int nextFacing = updateActorDirection(true); + if (_facing != nextFacing) { + // 2A89 + setDirection(nextFacing); + + if (_facing != _targetFacing ) { + _moving |= 0x80; + } else { + _moving &= ~0x80; + } + } else + _moving &= ~0x80; +} + void Actor_v2::walkActor() { Common::Point foundPath, tmp; int new_dir, next_box; @@ -985,18 +1389,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 +1419,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 +1493,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)->unk_FDE1 = 1; + ((Actor_v0*)this)->_CurrentWalkTo = _pos; + setDirection(oldDirToNewDir(2)); + } } static bool inBoxQuickReject(const BoxCoords &box, int x, int y, int threshold) { @@ -1410,6 +1824,7 @@ void Actor::showActor() { Actor_v0 *a = ((Actor_v0 *)this); a->_costCommand = a->_costCommandNew = 0xFF; + for (int i = 0; i < 8; ++i) { a->_limbFrameRepeat[i] = 0; @@ -1659,8 +2074,15 @@ void ScummEngine::processActors() { // would hence cause regressions. See also the other big // comment further up in this method for some details. if (a->_costume) { + + if (_game.version == 0) + a->animateCostume(); + a->drawActorCostume(); - a->animateCostume(); + + if (_game.version != 0) + a->animateCostume(); + } } } diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index 46dc7d0295..b2245da3d2 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -354,6 +354,27 @@ public: byte _miscflags; byte _speaking; + Common::Point _CurrentWalkTo, _NewWalkTo; + + byte _walkDirX; + byte _walkDirY; + + byte _walkYCountGreaterThanXCount; + byte _walkXCount; + byte _walkXCountInc; + byte _walkYCount; + byte _walkYCountInc; + byte _walkCountModulo; + + byte _walkMaxXYCountInc; + + byte unk_FDE1; + + Common::Point _tmp_Pos; + Common::Point _tmp_Dest; + byte _tmp_WalkBox; + byte _tmp_CB5F; + int8 _animFrameRepeat; int8 _limbFrameRepeatNew[8]; int8 _limbFrameRepeat[8]; @@ -363,16 +384,27 @@ 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 sub_2F6F(); + void walkActor(); + void actorSetWalkTo(); + byte actorWalkX(); + byte actorWalkY(); + byte updateWalkbox(); + byte walkboxFindTarget(); + void setTmpFromActor(); + void setActorFromTmp(); + // Used by the save/load system: virtual void saveLoadWithSerializer(Serializer *ser); diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index 2fe5333bfc..efd5e7bd2c 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -1179,7 +1179,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..6cbfbf45b3 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -589,9 +589,9 @@ void ScummEngine_v0::o_loadRoomWithEgo() { return; } - // The original interpreter sets the actors new room X/Y to the last rooms X/Y - // This fixes a problem with MM: script 158 in room 12, the 'Oomph!' script - // This scripts runs before the actor position is set to the correct room entry location + // The original interpreter seems to set the actors new room X/Y to the last rooms X/Y + // This fixes a problem with MM: script 158 in room 12, the 'Oompf!' script + // This scripts runs before the actor position is set to the correct location a->putActor(a->getPos().x, a->getPos().y, room); _egoPositioned = false; @@ -714,10 +714,8 @@ 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/verbs.cpp b/engines/scumm/verbs.cpp index fdb98a8019..c1bafe1e0f 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -717,7 +717,6 @@ void ScummEngine_v0::verbExec() { if (a->_miscflags & kActorMiscFlagFreeze) return; - a->stopActorMoving(); a->startWalkActor(VAR(6), VAR(7), -1); } -- cgit v1.2.3 From 29d46e8a10b7fae45d833bee0e7d3e4e62d75c5c Mon Sep 17 00:00:00 2001 From: Robert Crossfield Date: Sat, 29 Nov 2014 07:12:57 +1100 Subject: SCUMM: Maniac V0: If boxes are neighbors, walk directly to the new box. Remove extra call to 'animateCostume'. Remove now unnecessary V0 walk calc functions --- engines/scumm/actor.cpp | 211 ++++++++++++-------------------------------- engines/scumm/actor.h | 20 ++--- engines/scumm/boxes.cpp | 24 +++++ engines/scumm/script_v0.cpp | 7 +- engines/scumm/scumm_v0.h | 4 +- engines/scumm/verbs.cpp | 1 - 6 files changed, 92 insertions(+), 175 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 1ea1f6eb54..636f718582 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" @@ -453,7 +454,7 @@ void Actor::startWalkActor(int destX, int destY, int dir) { if(_vm->_game.version != 0 ) { _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG; } else { - ((Actor_v0*)this)->unk_FDE1 = 1; + ((Actor_v0*)this)->_newWalkBoxEntered = 1; } _walkdata.point3.x = 32000; @@ -574,91 +575,7 @@ 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; -} - -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 - - double det = v2.x * v1.y - v1.x * v2.y; - if (det == 0) - return false; - - 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; - - // 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; - - result.x = line1Start.x + (int)(n1 * v1.x); - result.y = line1Start.y + (int)(n1 * v1.y); - return true; -} - -/* - * 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); - } - } - - return false; -} - -bool Actor_v0::sub_2F6F() { +bool Actor_v0::calcWalkDistances() { _walkDirX = 0; _walkDirY = 0; _walkYCountGreaterThanXCount = 0; @@ -710,7 +627,7 @@ byte Actor_v0::updateWalkbox() { if (_walkdata.curbox == i ) { setBox(i); - unk_FDE1 = 1; + _newWalkBoxEntered = 1; return i; } } @@ -723,14 +640,14 @@ void Actor_v0::setTmpFromActor() { _tmp_Pos = _pos; _pos = _tmp_Dest; _tmp_WalkBox = _walkbox; - _tmp_CB5F = unk_FDE1; + _tmp_NewWalkBoxEntered = _newWalkBoxEntered; } void Actor_v0::setActorFromTmp() { _pos = _tmp_Pos; _tmp_Dest = _tmp_Pos; _walkbox = _tmp_WalkBox; - unk_FDE1 = _tmp_CB5F; + _newWalkBoxEntered = _tmp_NewWalkBoxEntered; } byte Actor_v0::actorWalkX() { @@ -748,21 +665,20 @@ byte Actor_v0::actorWalkX() { // 2EAC _walkXCount = A; setTmpFromActor(); - if( updateWalkbox() == 0xFF ) { + if (updateWalkbox() == 0xFF) { // 2EB9 setActorFromTmp(); return 3; } // 2EBF - if( _tmp_Dest.x == _CurrentWalkTo.x ) + if (_tmp_Dest.x == _CurrentWalkTo.x) return 1; return 0; } byte Actor_v0::actorWalkY() { - byte A = _walkYCount; A += _walkYCountInc; if (A >= _walkCountModulo) { @@ -782,15 +698,13 @@ byte Actor_v0::actorWalkY() { setActorFromTmp(); return 4; } - // 2EFE if (_walkYCountInc != 0) { - if (_walkYCountInc == 0xFF ) { + if (_walkYCountInc == 0xFF) { setActorFromTmp(); return 4; } } - // 2F0D if (_CurrentWalkTo.y == _tmp_Dest.y) return 1; @@ -798,31 +712,33 @@ byte Actor_v0::actorWalkY() { return 0; } -byte Actor_v0::walkboxFindTarget() { - return 0xff; -} +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::actorSetWalkTo() { - if (unk_FDE1 == 0 ) + if (_newWalkBoxEntered == 0) return; - unk_FDE1 = 0; - byte nextBox = _vm->getNextBox(_walkbox, _walkdata.destbox); + _newWalkBoxEntered = 0; - if (nextBox != 0xFF && nextBox != _walkbox ) { - Common::Point tmp; + int nextBox = ((ScummEngine_v0*)_vm)->walkboxFindTarget( this, _walkdata.destbox, _walkdata.dest ); + if (nextBox != 0xFF) { _walkdata.curbox = nextBox; - - getClosestPtOnBox(_vm->getBoxCoordinates(nextBox), _pos.x, _pos.y, _NewWalkTo.x, _NewWalkTo.y); - //getClosestPtOnBox(_vm->getBoxCoordinates(_walkbox), tmp.x, tmp.y, _NewWalkTo.x, _NewWalkTo.y); - - - } else { - if( _walkdata.dest.x == -1 ) - _NewWalkTo = _CurrentWalkTo; - else - _NewWalkTo = _walkdata.dest; } } @@ -839,7 +755,7 @@ loc_2A33:; _moving &= 0xF0; _tmp_Dest = _pos; - byte tmp = sub_2F6F(); + byte tmp = calcWalkDistances(); _moving &= 0xF0; _moving |= tmp; @@ -859,7 +775,7 @@ loc_2A33:; directionUpdate(); - if (_moving & 0x80 ) + if (_moving & 0x80) return; animateActor(newDirToOldDir(_facing)); @@ -876,17 +792,17 @@ loc_2A33:; // 2A9A - if (_moving == 2 ) + if (_moving == 2) return; - if ((_moving & 0x0F) == 1 ) + if ((_moving & 0x0F) == 1) return stopActorMoving(); // 2AAD if (_moving & 0x80) { directionUpdate(); - if ((_moving & 0x80) ) + if (_moving & 0x80) return; // 2AC2 @@ -899,7 +815,7 @@ loc_2C36:; // 2C36 setTmpFromActor(); - if (!_walkDirX ) { + if (!_walkDirX) { _pos.x--; } else { _pos.x++; @@ -944,7 +860,7 @@ loc_2C36:; } // 2ADA - if ((_moving & 0x0F) == 4 ) { + if ((_moving & 0x0F) == 4) { // 2CA3 loc_2CA3:; setTmpFromActor(); @@ -954,22 +870,22 @@ loc_2CA3:; } else { _pos.y++; } - if (updateWalkbox() == 0xFF ) { + if (updateWalkbox() == 0xFF) { // 2CC7 setActorFromTmp(); - if( _CurrentWalkTo.x == _tmp_Dest.x ) { + if( _CurrentWalkTo.x == _tmp_Dest.x) { stopActorMoving(); return; } // 2CD5 - if (!_walkDirX ) { + if (!_walkDirX) { _tmp_Dest.x--; } else { _tmp_Dest.x++; } setTmpFromActor(); - if (updateWalkbox() == 0xFF ) { + if (updateWalkbox() == 0xFF) { setActorFromTmp(); stopActorMoving(); } @@ -981,19 +897,19 @@ loc_2CA3:; } } - if ((_moving & 0x0F) == 0 ) { + if ((_moving & 0x0F) == 0) { // 2AE8 byte A = actorWalkX(); - if( A == 1 ) { + if (A == 1) { A = actorWalkY(); - if( A == 1 ) { + if (A == 1) { // 2AF6 _moving &= 0xF0; _moving |= A; } else { // 2B04 - if( A == 4 ) + if (A == 4) stopActorMoving(); } @@ -1018,7 +934,7 @@ loc_2CA3:; } else { // 2B39 A = actorWalkY(); - if (A != 4 ) + if (A != 4) return; // 2B46 @@ -1039,22 +955,6 @@ loc_2CA3:; } } -void Actor_v0::directionUpdate() { - - int nextFacing = updateActorDirection(true); - if (_facing != nextFacing) { - // 2A89 - setDirection(nextFacing); - - if (_facing != _targetFacing ) { - _moving |= 0x80; - } else { - _moving &= ~0x80; - } - } else - _moving &= ~0x80; -} - void Actor_v2::walkActor() { Common::Point foundPath, tmp; int new_dir, next_box; @@ -1101,10 +1001,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); } @@ -1496,7 +1394,7 @@ void Actor::putActor(int dstX, int dstY, int newRoom) { if (_vm->_game.version == 0) { _walkdata.dest = _pos; - ((Actor_v0*)this)->unk_FDE1 = 1; + ((Actor_v0*)this)->_newWalkBoxEntered = 1; ((Actor_v0*)this)->_CurrentWalkTo = _pos; setDirection(oldDirToNewDir(2)); @@ -2075,14 +1973,15 @@ void ScummEngine::processActors() { // comment further up in this method for some details. if (a->_costume) { - if (_game.version == 0) + // Unfortunately in V0, the 'animateCostume' call happens right after the call to 'walkActor', before drawing the actor... doing it the + // other way with V0, causes graphic glitches + if (_game.version == 0) { a->animateCostume(); - - a->drawActorCostume(); - - if (_game.version != 0) + a->drawActorCostume(); + } else { + a->drawActorCostume(); a->animateCostume(); - + } } } } diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index b2245da3d2..c554cad040 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,12 +348,15 @@ enum ActorV0MiscFlags { class Actor_v0 : public Actor_v2 { public: + Common::Point _CurrentWalkTo, _NewWalkTo; + byte _costCommandNew; byte _costCommand; byte _miscflags; byte _speaking; - Common::Point _CurrentWalkTo, _NewWalkTo; + byte _walkCountModulo; + byte _newWalkBoxEntered; byte _walkDirX; byte _walkDirY; @@ -364,16 +366,13 @@ public: byte _walkXCountInc; byte _walkYCount; byte _walkYCountInc; - byte _walkCountModulo; byte _walkMaxXYCountInc; - byte unk_FDE1; - Common::Point _tmp_Pos; Common::Point _tmp_Dest; byte _tmp_WalkBox; - byte _tmp_CB5F; + byte _tmp_NewWalkBoxEntered; int8 _animFrameRepeat; int8 _limbFrameRepeatNew[8]; @@ -395,23 +394,18 @@ public: void setDirection(int direction); void startAnimActor(int f); - bool sub_2F6F(); + bool calcWalkDistances(); void walkActor(); void actorSetWalkTo(); byte actorWalkX(); byte actorWalkY(); byte updateWalkbox(); - byte walkboxFindTarget(); + 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/script_v0.cpp b/engines/scumm/script_v0.cpp index 6cbfbf45b3..90291535fd 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -589,9 +589,9 @@ void ScummEngine_v0::o_loadRoomWithEgo() { return; } - // The original interpreter seems to set the actors new room X/Y to the last rooms X/Y - // This fixes a problem with MM: script 158 in room 12, the 'Oompf!' script - // This scripts runs before the actor position is set to the correct location + // The original interpreter sets the actors new room X/Y to the last rooms X/Y + // This fixes a problem with MM: script 158 in room 12, the 'Oomph!' script + // This scripts runs before the actor position is set to the correct room entry location a->putActor(a->getPos().x, a->getPos().y, room); _egoPositioned = false; @@ -707,7 +707,6 @@ void ScummEngine_v0::o_animateActor() { } a->animateActor(anim); - a->animateCostume(); } void ScummEngine_v0::o_getActorMoving() { 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 c1bafe1e0f..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; -- cgit v1.2.3 From 814d9b1153df417c184be2b1a9072d0c7b37b201 Mon Sep 17 00:00:00 2001 From: Robert Crossfield Date: Sun, 30 Nov 2014 22:01:23 +1100 Subject: SCUMM: Maniac V0: Correctly handle 'slanted' walk-boxes, Add new variables to save-games, Bump the SaveGame Version number, remove obsolete V0 code in V2 functions --- engines/scumm/actor.cpp | 504 +++++++++++++++++++++++++++-------------------- engines/scumm/actor.h | 7 +- engines/scumm/saveload.h | 2 +- engines/scumm/script.cpp | 6 +- 4 files changed, 296 insertions(+), 223 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 636f718582..90ee5bf368 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -51,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); @@ -183,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) { @@ -250,11 +270,11 @@ void Actor::stopActorMoving() { if (_walkScript) _vm->stopScript(_walkScript); - _moving = 0; - if (_vm->_game.version == 0) { _moving = 2; setDirection(_facing); + } else { + _moving = 0; } } @@ -343,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); @@ -354,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)) { @@ -393,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; @@ -451,14 +565,14 @@ void Actor::startWalkActor(int destX, int destY, int dir) { _walkdata.dest.y = abr.y; _walkdata.destbox = abr.box; _walkdata.destdir = dir; - if(_vm->_game.version != 0 ) { - _moving = (_moving & MF_IN_LEG) | MF_NEW_LEG; - } else { - ((Actor_v0*)this)->_newWalkBoxEntered = 1; - } _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) { @@ -575,183 +689,14 @@ void Actor::walkActor() { calcMovementFactor(_walkdata.dest); } -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::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); - - _newWalkBoxEntered = 1; - return i; - } - } - } - - return 0xFF; -} - -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; -} - -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() == 0xFF) { - // 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() == 0xFF) { - // 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_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::actorSetWalkTo() { - - if (_newWalkBoxEntered == 0) - return; - - _newWalkBoxEntered = 0; - - int nextBox = ((ScummEngine_v0*)_vm)->walkboxFindTarget( this, _walkdata.destbox, _walkdata.dest ); - if (nextBox != 0xFF) { - _walkdata.curbox = nextBox; - } -} - void Actor_v0::walkActor() { actorSetWalkTo(); _needRedraw = true; if (_NewWalkTo != _CurrentWalkTo) { - - // 2A27 _CurrentWalkTo = _NewWalkTo; -loc_2A33:; +L2A33:; _moving &= 0xF0; _tmp_Dest = _pos; @@ -784,13 +729,11 @@ loc_2A33:; // 2A0A if ((_moving & 0x7F) != 1) { - if (_NewWalkTo == _pos) { + if (_NewWalkTo == _pos) return; - } } } - // 2A9A if (_moving == 2) return; @@ -805,14 +748,11 @@ loc_2A33:; if (_moving & 0x80) return; - // 2AC2 animateActor(newDirToOldDir(_facing)); } - // 2ACE if ((_moving & 0x0F) == 3 ) { -loc_2C36:; - // 2C36 +L2C36:; setTmpFromActor(); if (!_walkDirX) { @@ -822,13 +762,12 @@ loc_2C36:; } // 2C51 - if (updateWalkbox() != 0xFF) { - //2C66 + if (updateWalkbox() != kInvalidBox) { + setActorFromTmp(); - goto loc_2A33; + goto L2A33; } - // 2C6C setActorFromTmp(); if (_CurrentWalkTo.y == _tmp_Dest.y) { @@ -841,8 +780,9 @@ loc_2C36:; } else { _tmp_Dest.y++; } + setTmpFromActor(); - //2C8B + byte A = updateWalkbox(); if (A == 0xFF) { setActorFromTmp(); @@ -861,8 +801,7 @@ loc_2C36:; // 2ADA if ((_moving & 0x0F) == 4) { - // 2CA3 -loc_2CA3:; +L2CA3:; setTmpFromActor(); if (!_walkDirY) { @@ -870,14 +809,14 @@ loc_2CA3:; } else { _pos.y++; } - if (updateWalkbox() == 0xFF) { + if (updateWalkbox() == kInvalidBox) { // 2CC7 setActorFromTmp(); if( _CurrentWalkTo.x == _tmp_Dest.x) { stopActorMoving(); return; } - // 2CD5 + if (!_walkDirX) { _tmp_Dest.x--; } else { @@ -885,7 +824,7 @@ loc_2CA3:; } setTmpFromActor(); - if (updateWalkbox() == 0xFF) { + if (updateWalkbox() == kInvalidBox) { setActorFromTmp(); stopActorMoving(); } @@ -893,22 +832,20 @@ loc_2CA3:; return; } else { setActorFromTmp(); - goto loc_2A33; + goto L2A33; } } if ((_moving & 0x0F) == 0) { - // 2AE8 + // 2AE8 byte A = actorWalkX(); if (A == 1) { A = actorWalkY(); - if (A == 1) { - // 2AF6 + if (A == 1) { _moving &= 0xF0; _moving |= A; } else { - // 2B04 if (A == 4) stopActorMoving(); } @@ -929,7 +866,7 @@ loc_2CA3:; directionUpdate(); animateActor(newDirToOldDir(_facing)); - goto loc_2C36; + goto L2C36; } else { // 2B39 @@ -937,7 +874,6 @@ loc_2CA3:; if (A != 4) return; - // 2B46 _moving &= 0xF0; _moving |= A; @@ -949,7 +885,7 @@ loc_2CA3:; directionUpdate(); animateActor(newDirToOldDir(_facing)); - goto loc_2CA3; + goto L2CA3; } } } @@ -1394,7 +1330,7 @@ void Actor::putActor(int dstX, int dstY, int newRoom) { if (_vm->_game.version == 0) { _walkdata.dest = _pos; - ((Actor_v0*)this)->_newWalkBoxEntered = 1; + ((Actor_v0*)this)->_newWalkBoxEntered = true; ((Actor_v0*)this)->_CurrentWalkTo = _pos; setDirection(oldDirToNewDir(2)); @@ -1512,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; @@ -1722,7 +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; @@ -1955,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++; @@ -1973,8 +1962,9 @@ void ScummEngine::processActors() { // comment further up in this method for some details. if (a->_costume) { - // Unfortunately in V0, the 'animateCostume' call happens right after the call to 'walkActor', before drawing the actor... doing it the - // other way with V0, causes graphic glitches + // 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(); @@ -3218,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); @@ -3231,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 c554cad040..c1a3f23318 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -356,7 +356,7 @@ public: byte _speaking; byte _walkCountModulo; - byte _newWalkBoxEntered; + bool _newWalkBoxEntered; byte _walkDirX; byte _walkDirY; @@ -372,7 +372,7 @@ public: Common::Point _tmp_Pos; Common::Point _tmp_Dest; byte _tmp_WalkBox; - byte _tmp_NewWalkBoxEntered; + bool _tmp_NewWalkBoxEntered; int8 _animFrameRepeat; int8 _limbFrameRepeatNew[8]; @@ -401,6 +401,9 @@ public: byte actorWalkY(); byte updateWalkbox(); + AdjustBoxResult adjustXYToBeInBox(int dstX, int dstY); + AdjustBoxResult adjustPosInBorderWalkbox(AdjustBoxResult box); + void setTmpFromActor(); void setActorFromTmp(); 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 efd5e7bd2c..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!=2) + if (a->_moving != 2) return true; // after walking and turning finally execute the script -- cgit v1.2.3 From 4b1b9ec66f5889fd20d88f8f7f565e8448ac8389 Mon Sep 17 00:00:00 2001 From: Robert Crossfield Date: Tue, 2 Dec 2014 16:40:46 +1100 Subject: SCUMM: Maniac V0: Remove workaround for bug #2971126 (this issue no longer occurs as walking is handled the same as the original) --- engines/scumm/script_v5.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engines/scumm') 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() { -- cgit v1.2.3