From be052be462c6d6b9f47b57b1169cc5e1e306d65f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 4 Feb 2007 01:24:43 +0000 Subject: Rewrote the actor walk code for SCUMM V0-V2 games: Now it uses the C64 character coordinates internally, not pixel coordinates. This should fix some walk bugs, but also might cause some regressions. Watch out svn-id: r25370 --- engines/scumm/actor.cpp | 65 ++++++++++++++++++++++++++++++++++---------- engines/scumm/actor.h | 18 ++++++++++-- engines/scumm/boxes.cpp | 40 +++++++++++++-------------- engines/scumm/debugger.cpp | 11 ++++++-- engines/scumm/object.cpp | 26 +++++++----------- engines/scumm/saveload.cpp | 2 +- engines/scumm/saveload.h | 2 +- engines/scumm/script_c64.cpp | 4 +-- engines/scumm/script_v2.cpp | 29 ++++++++------------ engines/scumm/script_v5.cpp | 12 +++++--- engines/scumm/verbs.cpp | 2 +- 11 files changed, 131 insertions(+), 80 deletions(-) (limited to 'engines') diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index e8c087e160..fccd07106d 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -87,8 +87,13 @@ void Actor::initActor(int mode) { _costumeNeedsInit = false; _visible = false; _flip = false; - _speedx = 8; - _speedy = 2; + if (_vm->_game.version <= 2) { + _speedx = 1; + _speedy = 1; + } else { + _speedx = 8; + _speedy = 2; + } _frame = 0; _walkbox = 0; _animProgress = 0; @@ -128,7 +133,11 @@ void Actor::initActor(int mode) { stopActorMoving(); - setActorWalkSpeed(8, 2); + if (_vm->_game.version <= 2) + setActorWalkSpeed(1, 1); + else + setActorWalkSpeed(8, 2); + _animSpeed = 0; if (_vm->_game.version >= 6) _animProgress = 0; @@ -173,14 +182,13 @@ void Actor::setBox(int box) { setupActorScale(); } -void Actor::setupActorScale() { - - if (_vm->_game.features & GF_NO_SCALING) { - _scalex = 0xFF; - _scaley = 0xFF; - return; - } +void ActorOldWalk::setupActorScale() { + // TODO: The following could probably be removed + _scalex = 0xFF; + _scaley = 0xFF; +} +void Actor::setupActorScale() { if (_ignoreBoxes) return; @@ -510,7 +518,7 @@ void Actor::walkActor() { } /* -void Actor::walkActorV12() { +void Actor::walkActor() { Common::Point foundPath, tmp; int new_dir, next_box; @@ -961,8 +969,6 @@ AdjustBoxResult Actor::adjustXYToBeInBox(int dstX, int dstY) { return abr; bestDist = (_vm->_game.version >= 7) ? 0x7FFFFFFF : 0xFFFF; - if (_vm->_game.version <= 2) // Adjust for the fact that we multiply x by 8 and y by 2 - bestDist *= V12_X_MULTIPLIER * V12_Y_MULTIPLIER; bestBox = kInvalidBox; // We iterate (backwards) over all boxes, searching the one closest @@ -1326,9 +1332,15 @@ void Actor::drawActorCostume(bool hitTestMode) { bcr->_actorID = _number; - bcr->_actorX = _pos.x + _offsX - _vm->virtscr[0].xstart; + bcr->_actorX = _pos.x + _offsX; bcr->_actorY = _pos.y + _offsY - _elevation; + if (_vm->_game.version <= 2) { + bcr->_actorX *= V12_X_MULTIPLIER; + bcr->_actorY *= V12_Y_MULTIPLIER; + } + bcr->_actorX -= _vm->virtscr[0].xstart; + if (_vm->_game.platform == Common::kPlatformNES) { // In the NES version, when the actor is facing right, // we need to shift it 8 pixels to the left @@ -2354,6 +2366,31 @@ void Actor::saveLoadWithSerializer(Serializer *ser) { } ser->saveLoadEntries(this, actorEntries); + + if (ser->isLoading() && _vm->_game.version <= 2 && ser->getVersion() < VER(70)) { + _pos.x /= V12_X_MULTIPLIER; + _pos.y /= V12_Y_MULTIPLIER; + + _speedx /= V12_X_MULTIPLIER; + _speedy /= V12_Y_MULTIPLIER; + _elevation /= V12_Y_MULTIPLIER; + + if (_walkdata.dest.x != -1) { + _walkdata.dest.x /= V12_X_MULTIPLIER; + _walkdata.dest.y /= V12_Y_MULTIPLIER; + } + + _walkdata.cur.x /= V12_X_MULTIPLIER; + _walkdata.cur.y /= V12_Y_MULTIPLIER; + + _walkdata.next.x /= V12_X_MULTIPLIER; + _walkdata.next.y /= V12_Y_MULTIPLIER; + + if (_walkdata.point3.x != 32000) { + _walkdata.point3.x /= V12_X_MULTIPLIER; + _walkdata.point3.y /= V12_Y_MULTIPLIER; + } + } } } // End of namespace Scumm diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index e3f2deb2e9..f590f61e11 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -189,6 +189,10 @@ public: putActor(_pos.x, _pos.y, _room); } + void putActor(int room) { + putActor(_pos.x, _pos.y, room); + } + void putActor(int x, int y) { putActor(x, y, _room); } @@ -199,7 +203,7 @@ protected: int calcMovementFactor(const Common::Point& next); int actorWalkStep(); int remapDirection(int dir, bool is_walking); - void setupActorScale(); + virtual void setupActorScale(); void setBox(int box); int updateActorDirection(bool is_walking); @@ -239,7 +243,16 @@ public: return _room == _vm->_currentRoom; } - const Common::Point &getPos() const { + Common::Point getPos() const { + Common::Point p(_pos); + if (_vm->_game.version <= 2) { + p.x *= V12_X_MULTIPLIER; + p.y *= V12_Y_MULTIPLIER; + } + return p; + } + + const Common::Point& getRealPos() const { return _pos; } @@ -323,6 +336,7 @@ public: virtual void walkActor(); protected: + virtual void setupActorScale(); void findPathTowardsOld(byte box, byte box2, byte box3, Common::Point &p2, Common::Point &p3); }; diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp index 12e90b2d77..91752cfc34 100644 --- a/engines/scumm/boxes.cpp +++ b/engines/scumm/boxes.cpp @@ -240,7 +240,7 @@ void ScummEngine::setBoxScaleSlot(int box, int slot) { } int ScummEngine::getScale(int box, int x, int y) { - if (_game.features & GF_NO_SCALING) + if (_game.version <= 3) return 255; Box *ptr = getBoxBaseAddr(box); @@ -306,7 +306,7 @@ int ScummEngine::getScaleFromSlot(int slot, int x, int y) { } int ScummEngine::getBoxScale(int box) { - if (_game.features & GF_NO_SCALING) + if (_game.version <= 3) return 255; Box *ptr = getBoxBaseAddr(box); if (!ptr) @@ -600,25 +600,25 @@ BoxCoords ScummEngine::getBoxCoordinates(int boxnum) { SWAP(box->ll, box->lr); } } else if (_game.version == 0) { - box->ul.x = bp->c64.x1 * V12_X_MULTIPLIER; - box->ul.y = bp->c64.y1 * V12_Y_MULTIPLIER; - box->ur.x = bp->c64.x2 * V12_X_MULTIPLIER; - box->ur.y = bp->c64.y1 * V12_Y_MULTIPLIER; - - box->ll.x = bp->c64.x1 * V12_X_MULTIPLIER; - box->ll.y = bp->c64.y2 * V12_Y_MULTIPLIER; - box->lr.x = bp->c64.x2 * V12_X_MULTIPLIER; - box->lr.y = bp->c64.y2 * V12_Y_MULTIPLIER; + box->ul.x = bp->c64.x1; + box->ul.y = bp->c64.y1; + box->ur.x = bp->c64.x2; + box->ur.y = bp->c64.y1; + + box->ll.x = bp->c64.x1; + box->ll.y = bp->c64.y2; + box->lr.x = bp->c64.x2; + box->lr.y = bp->c64.y2; } else if (_game.version <= 2) { - box->ul.x = bp->v2.ulx * V12_X_MULTIPLIER; - box->ul.y = bp->v2.uy * V12_Y_MULTIPLIER; - box->ur.x = bp->v2.urx * V12_X_MULTIPLIER; - box->ur.y = bp->v2.uy * V12_Y_MULTIPLIER; - - box->ll.x = bp->v2.llx * V12_X_MULTIPLIER; - box->ll.y = bp->v2.ly * V12_Y_MULTIPLIER; - box->lr.x = bp->v2.lrx * V12_X_MULTIPLIER; - box->lr.y = bp->v2.ly * V12_Y_MULTIPLIER; + box->ul.x = bp->v2.ulx; + box->ul.y = bp->v2.uy; + box->ur.x = bp->v2.urx; + box->ur.y = bp->v2.uy; + + box->ll.x = bp->v2.llx; + box->ll.y = bp->v2.ly; + box->lr.x = bp->v2.lrx; + box->lr.y = bp->v2.ly; } else { box->ul.x = (int16)READ_LE_UINT16(&bp->old.ulx); box->ul.y = (int16)READ_LE_UINT16(&bp->old.uly); diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index a7637c6970..2d5b8a5dfa 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -383,11 +383,11 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { a->_ignoreBoxes = (value > 0); DebugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes); } else if (!strcmp(argv[2], "x")) { - a->putActor(value, a->getPos().y); + a->putActor(value, a->getRealPos().y); DebugPrintf("Actor[%d].x = %d\n", actnum, a->getPos().x); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "y")) { - a->putActor(a->getPos().x, value); + a->putActor(a->getRealPos().x, value); DebugPrintf("Actor[%d].y = %d\n", actnum, a->getPos().y); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "_elevation")) { @@ -754,6 +754,13 @@ void ScummDebugger::drawBox(int box) { r[1] = coords.ur; r[2] = coords.lr; r[3] = coords.ll; + + if (_vm->_game.version <= 2) { + for (int i = 0; i < 4; ++i) { + r[i].x *= V12_X_MULTIPLIER; + r[i].y *= V12_Y_MULTIPLIER; + } + } // TODO - maybe use different colors for each box, and/or print the box number inside it? fillQuad(_vm, r, 13); diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index 4a48c44467..b3c3b9cb8a 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -340,8 +340,8 @@ int ScummEngine::getObjectOrActorXY(int object, int &x, int &y) { if (object < _numActors) { act = derefActorSafe(object, "getObjectOrActorXY"); if (act && act->isInCurrentRoom()) { - x = act->getPos().x; - y = act->getPos().y; + x = act->getRealPos().x; + y = act->getRealPos().y; return 0; } else return -1; @@ -354,8 +354,8 @@ int ScummEngine::getObjectOrActorXY(int object, int &x, int &y) { if (_objectOwnerTable[object] < _numActors) { act = derefActor(_objectOwnerTable[object], "getObjectOrActorXY(2)"); if (act && act->isInCurrentRoom()) { - x = act->getPos().x; - y = act->getPos().y; + x = act->getRealPos().x; + y = act->getRealPos().y; return 0; } } @@ -412,6 +412,9 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) { x = od.x_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].x); y = od.y_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].y); } + } else if (_game.version <= 2) { + x = od.walk_x / V12_X_MULTIPLIER; + y = od.walk_y / V12_Y_MULTIPLIER; } else { x = od.walk_x; y = od.walk_y; @@ -458,17 +461,8 @@ int ScummEngine::getObjActToObjActDist(int a, int b) { y2 = r.y; } - // Now compute the distance between the two points - if (_game.version <= 2) { - // For V1/V2 games, distances are measured in the original "character" - // based coordinate system, instead of pixels. Otherwise various scripts - // will break. See bugs #853874, #774529 - x /= V12_X_MULTIPLIER; - y /= V12_Y_MULTIPLIER; - x2 /= V12_X_MULTIPLIER; - y2 /= V12_Y_MULTIPLIER; - } + // Now compute the distance between the two points return getDist(x, y, x2, y2); } @@ -1449,7 +1443,7 @@ int ScummEngine::getObjX(int obj) { if (obj < _numActors) { if (obj < 1) return 0; /* fix for indy4's map */ - return derefActor(obj, "getObjX")->getPos().x; + return derefActor(obj, "getObjX")->getRealPos().x; } else { if (whereIsObject(obj) == WIO_NOT_FOUND) return -1; @@ -1463,7 +1457,7 @@ int ScummEngine::getObjY(int obj) { if (obj < _numActors) { if (obj < 1) return 0; /* fix for indy4's map */ - return derefActor(obj, "getObjY")->getPos().y; + return derefActor(obj, "getObjY")->getRealPos().y; } else { if (whereIsObject(obj) == WIO_NOT_FOUND) return -1; diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 684d6972e4..e8771b68f2 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -901,7 +901,7 @@ void ScummEngine::saveOrLoad(Serializer *s) { debug(2, "Saved game MD5: %s", (s->getVersion() >= 39) ? md5str1 : "unknown"); if (memcmp(md5Backup, _gameMD5, 16) != 0) { - warning("Game was saved with different gamedata - you may encounter problems."); + warning("Game was saved with different gamedata - you may encounter problems"); debug(1, "You have %s and save is %s.", md5str2, md5str1); memcpy(_gameMD5, md5Backup, 16); } diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index e20c333f0c..659b37a330 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 69 +#define CURRENT_VER 70 /** * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/engines/scumm/script_c64.cpp b/engines/scumm/script_c64.cpp index 70f2ab35ed..d47f264b1e 100644 --- a/engines/scumm/script_c64.cpp +++ b/engines/scumm/script_c64.cpp @@ -745,8 +745,8 @@ void ScummEngine_c64::o_putActorAtObject() { if (whereIsObject(obj) != WIO_NOT_FOUND) getObjectXYPos(obj, x, y); else { - x = 240; - y = 120; + x = 30; + y = 60; } a->putActor(x, y); diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp index beccc6d116..7322a8f9d9 100644 --- a/engines/scumm/script_v2.cpp +++ b/engines/scumm/script_v2.cpp @@ -818,9 +818,6 @@ void ScummEngine_v2::o2_verbOps() { break; default: { // New Verb - // FIXME: maybe use V12_X_MULTIPLIER here... maybe not. Depends - // on whether verbs can be handled separately from objects and - // actors or not when it comes to handling coordinates. int x = fetchScriptByte() * 8; int y = fetchScriptByte() * 8; slot = getVarOrDirectByte(PARAM_1) + 1; @@ -1133,8 +1130,8 @@ void ScummEngine_v2::o2_walkActorTo() { a = derefActor(act, "o2_walkActorTo"); - x = getVarOrDirectByte(PARAM_2) * V12_X_MULTIPLIER; - y = getVarOrDirectByte(PARAM_3) * V12_Y_MULTIPLIER; + x = getVarOrDirectByte(PARAM_2); + y = getVarOrDirectByte(PARAM_3); a->startWalkActor(x, y, -1); } @@ -1146,8 +1143,8 @@ void ScummEngine_v2::o2_putActor() { a = derefActor(act, "o2_putActor"); - x = getVarOrDirectByte(PARAM_2) * V12_X_MULTIPLIER; - y = getVarOrDirectByte(PARAM_3) * V12_Y_MULTIPLIER; + x = getVarOrDirectByte(PARAM_2); + y = getVarOrDirectByte(PARAM_3); if (_game.id == GID_MANIAC && _game.version <= 1 && _game.platform != Common::kPlatformNES) a->setFacing(180); @@ -1213,13 +1210,12 @@ void ScummEngine_v2::o2_putActorAtObject() { Actor *a; a = derefActor(getVarOrDirectByte(PARAM_1), "o2_putActorAtObject"); - obj = getVarOrDirectWord(PARAM_2); if (whereIsObject(obj) != WIO_NOT_FOUND) getObjectXYPos(obj, x, y); else { - x = 240; - y = 120; + x = 30; + y = 60; } a->putActor(x, y); @@ -1245,7 +1241,7 @@ void ScummEngine_v2::o2_getActorElevation() { getResultPos(); int act = getVarOrDirectByte(PARAM_1); Actor *a = derefActor(act, "o2_getActorElevation"); - setResult(a->getElevation() / V12_Y_MULTIPLIER); + setResult(a->getElevation()); } void ScummEngine_v2::o2_setActorElevation() { @@ -1253,7 +1249,7 @@ void ScummEngine_v2::o2_setActorElevation() { int elevation = (int8)getVarOrDirectByte(PARAM_2); Actor *a = derefActor(act, "o2_setActorElevation"); - a->setElevation(elevation * V12_Y_MULTIPLIER); + a->setElevation(elevation); } void ScummEngine_v2::o2_actorFromPos() { @@ -1282,7 +1278,7 @@ void ScummEngine_v2::o2_getActorX() { getResultPos(); a = getVarOrDirectByte(PARAM_1); - setResult(getObjX(a) / V12_X_MULTIPLIER); + setResult(getObjX(a)); } void ScummEngine_v2::o2_getActorY() { @@ -1290,7 +1286,7 @@ void ScummEngine_v2::o2_getActorY() { getResultPos(); a = getVarOrDirectByte(PARAM_1); - setResult(getObjY(a) / V12_Y_MULTIPLIER); + setResult(getObjY(a)); } void ScummEngine_v2::o2_isGreater() { @@ -1371,8 +1367,8 @@ void ScummEngine_v2::o2_loadRoomWithEgo() { a->putActor(0, 0, room); _egoPositioned = false; - x = (int8)fetchScriptByte() * V12_X_MULTIPLIER; - y = (int8)fetchScriptByte() * V12_Y_MULTIPLIER; + x = (int8)fetchScriptByte(); + y = (int8)fetchScriptByte(); startScene(a->_room, a, obj); @@ -1433,7 +1429,6 @@ void ScummEngine_v2::o2_roomOps() { _opcode = fetchScriptByte(); switch (_opcode & 0x1F) { case 1: // SO_ROOM_SCROLL - // FIXME: Use V12_X_MULTIPLIER... ? a *= 8; b *= 8; if (a < (_screenWidth / 2)) diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index 53c686c91e..b335d569a8 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -1329,7 +1329,7 @@ void ScummEngine_v5::o5_isActorInBox() { int box = getVarOrDirectByte(PARAM_2); Actor *a = derefActor(act, "o5_isActorInBox"); - if (!checkXYInBoxBounds(box, a->getPos().x, a->getPos().y)) + if (!checkXYInBoxBounds(box, a->getRealPos().x, a->getRealPos().y)) o5_jumpRelative(); else ignoreScriptWord(); @@ -1488,7 +1488,7 @@ void ScummEngine_v5::o5_loadRoomWithEgo() { a = derefActor(VAR(VAR_EGO), "o5_loadRoomWithEgo"); - a->putActor(a->getPos().x, a->getPos().y, room); + a->putActor(room); oldDir = a->getFacing(); _egoPositioned = false; @@ -2630,9 +2630,9 @@ implement a proper fix. if (!a2->isInCurrentRoom()) return; - if (_game.version <= 2) + if (_game.version <= 2) { dist *= V12_X_MULTIPLIER; - else if (dist == 0xFF) { + } else if (dist == 0xFF) { dist = a->_scalex * a->_width / 0xFF; dist += (a2->_scalex * a2->_width / 0xFF) / 2; } @@ -2643,6 +2643,10 @@ implement a proper fix. else x -= dist; + if (_game.version <= 2) { + x /= V12_X_MULTIPLIER; + y /= V12_Y_MULTIPLIER; + } if (_game.version <= 3) { AdjustBoxResult abr = a->adjustXYToBeInBox(x, y); x = abr.x; diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index 23f7038898..d76d3dce92 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -606,7 +606,7 @@ void ScummEngine_c64::checkExecVerbs() { runObject(_activeObject, entry); } else if (zone->number == kMainVirtScreen) { a = derefActor(VAR(VAR_EGO), "checkExecVerbs"); - a->startWalkActor(_virtualMouse.x, _virtualMouse.y, -1); + a->startWalkActor(_virtualMouse.x / V12_X_MULTIPLIER, _virtualMouse.y / V12_Y_MULTIPLIER, -1); } _activeInventory = 0; -- cgit v1.2.3