aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorMax Horn2007-02-04 01:24:43 +0000
committerMax Horn2007-02-04 01:24:43 +0000
commitbe052be462c6d6b9f47b57b1169cc5e1e306d65f (patch)
tree2cd26c677700d2aeae426a8584e4a6945a7e89df /engines/scumm
parentb2748810863483b6e249a262e6a18a805d1f3aa8 (diff)
downloadscummvm-rg350-be052be462c6d6b9f47b57b1169cc5e1e306d65f.tar.gz
scummvm-rg350-be052be462c6d6b9f47b57b1169cc5e1e306d65f.tar.bz2
scummvm-rg350-be052be462c6d6b9f47b57b1169cc5e1e306d65f.zip
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
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/actor.cpp65
-rw-r--r--engines/scumm/actor.h18
-rw-r--r--engines/scumm/boxes.cpp40
-rw-r--r--engines/scumm/debugger.cpp11
-rw-r--r--engines/scumm/object.cpp26
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script_c64.cpp4
-rw-r--r--engines/scumm/script_v2.cpp29
-rw-r--r--engines/scumm/script_v5.cpp12
-rw-r--r--engines/scumm/verbs.cpp2
11 files changed, 131 insertions, 80 deletions
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;