aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/actor.cpp
diff options
context:
space:
mode:
authorRobert Crossfield2014-11-29 07:12:57 +1100
committerRobert Crossfield2014-11-29 09:07:10 +1100
commit29d46e8a10b7fae45d833bee0e7d3e4e62d75c5c (patch)
tree14e78113fac8cace5b0249cef7e14ccb129248fa /engines/scumm/actor.cpp
parent2dbd99d57264bab012cebd064eadfc34050832b1 (diff)
downloadscummvm-rg350-29d46e8a10b7fae45d833bee0e7d3e4e62d75c5c.tar.gz
scummvm-rg350-29d46e8a10b7fae45d833bee0e7d3e4e62d75c5c.tar.bz2
scummvm-rg350-29d46e8a10b7fae45d833bee0e7d3e4e62d75c5c.zip
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
Diffstat (limited to 'engines/scumm/actor.cpp')
-rw-r--r--engines/scumm/actor.cpp211
1 files changed, 55 insertions, 156 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();
-
+ }
}
}
}