aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/scumm/actor.cpp211
-rw-r--r--engines/scumm/actor.h20
-rw-r--r--engines/scumm/boxes.cpp24
-rw-r--r--engines/scumm/script_v0.cpp7
-rw-r--r--engines/scumm/scumm_v0.h4
-rw-r--r--engines/scumm/verbs.cpp1
6 files changed, 92 insertions, 175 deletions
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;