aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorRobert Crossfield2014-11-28 22:24:45 +1100
committerRobert Crossfield2014-11-28 22:24:45 +1100
commit2dbd99d57264bab012cebd064eadfc34050832b1 (patch)
treeaa476a621ea221f21ea3eebda2b42c45e4d1215b /engines/scumm
parent5beeadfd76ac001bf1bb9ebcb7b899892531efc5 (diff)
downloadscummvm-rg350-2dbd99d57264bab012cebd064eadfc34050832b1.tar.gz
scummvm-rg350-2dbd99d57264bab012cebd064eadfc34050832b1.tar.bz2
scummvm-rg350-2dbd99d57264bab012cebd064eadfc34050832b1.zip
SCUMM: Maniac V0: Implement the original Walk Code (to fix some anim glitches), fix opcode to use _moving correctly (as V0 is different)
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/actor.cpp440
-rw-r--r--engines/scumm/actor.h40
-rw-r--r--engines/scumm/script.cpp2
-rw-r--r--engines/scumm/script_v0.cpp12
-rw-r--r--engines/scumm/verbs.cpp1
5 files changed, 473 insertions, 22 deletions
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);
}