aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicola Mettifogo2009-02-24 11:20:45 +0000
committerNicola Mettifogo2009-02-24 11:20:45 +0000
commit6334125d1c0264278f2907d13cff8e6ba418bcc8 (patch)
treeacc886a51380e9b035213456cf74a6ee8d996030
parent5dff53a2fa8d2f7314d23e229d3c79aa3c0fc3bc (diff)
downloadscummvm-rg350-6334125d1c0264278f2907d13cff8e6ba418bcc8.tar.gz
scummvm-rg350-6334125d1c0264278f2907d13cff8e6ba418bcc8.tar.bz2
scummvm-rg350-6334125d1c0264278f2907d13cff8e6ba418bcc8.zip
Implemented follower support, except that:
* follower is forgotten when location changes (see freeLocation) * the final walking frame is screwed svn-id: r38838
-rw-r--r--engines/parallaction/exec_br.cpp5
-rw-r--r--engines/parallaction/objects.h3
-rw-r--r--engines/parallaction/parallaction.cpp3
-rw-r--r--engines/parallaction/parallaction.h2
-rw-r--r--engines/parallaction/parallaction_br.cpp24
-rw-r--r--engines/parallaction/parser_br.cpp2
-rw-r--r--engines/parallaction/walk.cpp187
-rw-r--r--engines/parallaction/walk.h8
8 files changed, 130 insertions, 104 deletions
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 09d8043ab7..274e8187ff 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -116,6 +116,11 @@ void Parallaction_br::clearSubtitles() {
DECLARE_COMMAND_OPCODE(location) {
warning("Parallaction_br::cmdOp_location command not yet implemented");
+ _vm->_location._startPosition = _ctxt.cmd->u._startPos;
+ _vm->_location._startFrame = 0; // TODO: verify this against the disassembly!f
+ _vm->_location._followerStartPosition = _ctxt.cmd->u._startPos2;
+ _vm->_location._followerStartFrame = 0;
+
// TODO: handle startPos and startPos2
_vm->scheduleLocationSwitch(_ctxt.cmd->u._string);
}
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index aa11165b33..9effbf66fd 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -229,6 +229,9 @@ struct DoorData {
GfxObj *gfxobj;
Common::Point _startPos;
uint16 _startFrame;
+ // BRA specific
+ Common::Point _startPos2;
+ uint16 _startFrame2;
DoorData() {
_location = NULL;
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 6ab94d3c54..5193433eea 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -111,6 +111,9 @@ Common::Error Parallaction::init() {
_location._startPosition.x = -1000;
_location._startPosition.y = -1000;
_location._startFrame = 0;
+ _location._followerStartPosition.x = -1000;
+ _location._followerStartPosition.y = -1000;
+ _location._followerStartFrame = 0;
_objects = 0;
_screenSize = _screenWidth * _screenHeight;
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 55eeabfa85..e86485d036 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -153,6 +153,8 @@ struct Location {
int _zeta1;
int _zeta2;
CommandList _escapeCommands;
+ Common::Point _followerStartPosition;
+ uint16 _followerStartFrame;
protected:
void freeAnimations();
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 4cfada2bc7..cb81bf1646 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -202,6 +202,8 @@ void Parallaction_br::freeLocation(bool removeAll) {
_gfx->freeLocationObjects();
+ // TODO: avoid removing needed animations from 'common.slf'
+ // when cleaning up!!!
_location._animations.remove(_char._ani);
_location.cleanup(removeAll);
_location._animations.push_front(_char._ani);
@@ -261,15 +263,27 @@ void Parallaction_br::changeLocation(char *location) {
// load new location
parseLocation(location);
- setFollower(_followerName);
-
if (_location._startPosition.x != -1000) {
- _char.setFoot(_location._startPosition);
+ _char._ani->setFoot(_location._startPosition);
_char._ani->setF(_location._startFrame);
- _location._startPosition.y = -1000;
- _location._startPosition.x = -1000;
}
+ // re-link the follower animation
+ setFollower(_followerName);
+ if (_follower) {
+ Common::Point p = _location._followerStartPosition;
+ if (p.x == -1000) {
+ _char._ani->getFoot(p);
+ }
+ _follower->setFoot(p);
+ _follower->setF(_location._followerStartFrame);
+ }
+
+ _location._startPosition.x = -1000;
+ _location._startPosition.y = -1000;
+ _location._followerStartPosition.x = -1000;
+ _location._followerStartPosition.y = -1000;
+
// kFlagsRemove is cleared because the character is visible by default.
// Commands can hide the character, anyway.
_char._ani->_flags &= ~kFlagsRemove;
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index d91c0b485c..eeaf132b9e 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -525,6 +525,8 @@ DECLARE_COMMAND_PARSER(location) {
ctxt.cmd->u._string = strdup(_tokens[1]);
ctxt.nextToken++;
+ ctxt.cmd->u._startPos.x = -1000;
+ ctxt.cmd->u._startPos2.x = -1000;
if (_tokens[ctxt.nextToken][0] != '\0') {
if (isdigit(_tokens[ctxt.nextToken][0]) || _tokens[ctxt.nextToken][0] == '-') {
ctxt.cmd->u._startPos.x = atoi(_tokens[ctxt.nextToken]);
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 6807884c7a..a4f07f9bfc 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -368,15 +368,18 @@ bool PathWalker_BR::directPathExists(const Common::Point &from, const Common::Po
void PathWalker_BR::setCharacterPath(AnimationPtr a, uint16 x, uint16 y) {
_character._a = a;
- _ch = _character;
- buildPath(x, y);
+ _character._first = true;
+ _character._fieldC = 1;
+ buildPath(_character, x, y);
_character._active = true;
}
void PathWalker_BR::setFollowerPath(AnimationPtr a, uint16 x, uint16 y) {
_follower._a = a;
- _ch = _follower;
- buildPath(x, y);
+ _follower._first = true;
+ _follower._fieldC = 1;
+ _follower._walkDelay = 5;
+ buildPath(_follower, x - 50, y);
_follower._active = true;
}
@@ -386,17 +389,17 @@ void PathWalker_BR::stopFollower() {
}
-void PathWalker_BR::buildPath(uint16 x, uint16 y) {
+void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
Common::Point foot;
- _ch._a->getFoot(foot);
+ s._a->getFoot(foot);
debugC(1, kDebugWalk, "buildPath: from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y);
- _ch._walkPath.clear();
+ s._walkPath.clear();
// look for easy path first
Common::Point dest(x, y);
if (directPathExists(foot, dest)) {
- _ch._walkPath.push_back(dest);
+ s._walkPath.push_back(dest);
debugC(3, kDebugWalk, "buildPath: direct path found");
return;
}
@@ -404,13 +407,13 @@ void PathWalker_BR::buildPath(uint16 x, uint16 y) {
// look for short circuit cases
ZonePtr z0 = _vm->hitZone(kZonePath, x, y);
if (!z0) {
- _ch._walkPath.push_back(dest);
+ s._walkPath.push_back(dest);
debugC(3, kDebugWalk, "buildPath: corner case 0");
return;
}
ZonePtr z1 = _vm->hitZone(kZonePath, foot.x, foot.y);
if (!z1 || z1 == z0) {
- _ch._walkPath.push_back(dest);
+ s._walkPath.push_back(dest);
debugC(3, kDebugWalk, "buildPath: corner case 1");
return;
}
@@ -419,7 +422,7 @@ void PathWalker_BR::buildPath(uint16 x, uint16 y) {
int id = atoi(z0->_name);
if (z1->u.path->_lists[id].empty()) {
- _ch._walkPath.clear();
+ s._walkPath.clear();
debugC(3, kDebugWalk, "buildPath: no path");
return;
}
@@ -427,39 +430,34 @@ void PathWalker_BR::buildPath(uint16 x, uint16 y) {
PointList::iterator b = z1->u.path->_lists[id].begin();
PointList::iterator e = z1->u.path->_lists[id].end();
for ( ; b != e; b++) {
- _ch._walkPath.push_front(*b);
+ s._walkPath.push_front(*b);
}
- _ch._walkPath.push_back(dest);
+ s._walkPath.push_back(dest);
debugC(3, kDebugWalk, "buildPath: complex path");
}
-void PathWalker_BR::finalizeWalk() {
+void PathWalker_BR::finalizeWalk(State &s) {
_engineFlags &= ~kEngineWalking;
- _ch._first = true;
- _ch._fieldC = 1;
Common::Point foot;
- _ch._a->getFoot(foot);
+ _character._a->getFoot(foot);
ZonePtr z = _vm->hitZone(kZoneDoor, foot.x, foot.y);
if (z && ((z->_flags & kFlagsClosed) == 0)) {
_vm->_location._startPosition = z->u.door->_startPos; // foot pos
_vm->_location._startFrame = z->u.door->_startFrame;
-#if 0
// TODO: implement working follower. Must find out a location in which the code is
// used and which is stable enough.
- _followerFootInit.x = -1;
- if (_follower && z->u.door->startPos2.x != -1) {
- _followerFootInit.x = z->u.door->startPos2.x; // foot pos
- _followerFootInit.y = z->u.door->startPos2.y; // foot pos
- }
- _followerFootInit.z = -1;
- if (_follower && z->u.door->startPos2.z != -1) {
- _followerFootInit.z = z->u.door->startPos2.z; // foot pos
+ if (_follower._active) {
+ _vm->_location._followerStartPosition = z->u.door->_startPos2; // foot pos
+ _vm->_location._followerStartFrame = z->u.door->_startFrame2;
+ } else {
+ _vm->_location._followerStartPosition.x = -1000;
+ _vm->_location._followerStartPosition.y = -1000;
+ _vm->_location._followerStartFrame = 0;
}
-#endif
_vm->scheduleLocationSwitch(z->u.door->_location);
_vm->_cmdExec->run(z->_commands, z);
@@ -467,8 +465,6 @@ void PathWalker_BR::finalizeWalk() {
#if 0
// TODO: Input::walkTo must be extended to support destination frame in addition to coordinates
- // TODO: the frame argument must be passed to PathWalker through PathBuilder, so probably
- // a merge between the two Path managers is the right solution
if (_engineFlags & FINAL_WALK_FRAME) { // this flag is set in readInput()
_engineFlags &= ~FINAL_WALK_FRAME;
_ch._a->_frame = _moveToF; // from readInput()...
@@ -478,7 +474,7 @@ void PathWalker_BR::finalizeWalk() {
_ch._a->setFoot(foot);
#endif
- _ch._a->setF(_ch._dirFrame); // temporary solution
+ s._a->setF(s._dirFrame); // temporary solution
#if 0
// TODO: support scrolling ;)
@@ -488,7 +484,7 @@ void PathWalker_BR::finalizeWalk() {
if (foot.y < 80) _gfx->scrollUp(100);
#endif
- return;
+ s._active = false;
}
void PathWalker_BR::walk() {
@@ -496,12 +492,12 @@ void PathWalker_BR::walk() {
return;
}
- bool finalize = doWalk(_character);
+ debugC(3, kDebugWalk, "PathWalker_BR::walk()");
+
+ doWalk(_character);
doWalk(_follower);
- if (finalize) {
- finalizeWalk();
- }
+ debugC(3, kDebugWalk, "PathWalker_BR::walk() -> done");
}
void PathWalker_BR::checkTrap(const Common::Point &p) {
@@ -530,12 +526,12 @@ void PathWalker_BR::checkTrap(const Common::Point &p) {
_vm->_zoneTrap = z;
}
-bool PathWalker_BR::doWalk(State &s) {
+void PathWalker_BR::doWalk(State &s) {
if (!s._active) {
- return false;
+ return;
}
- _ch = s;
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk(%s)", s._a->_name);
#if 0
// TODO: support delays in walking. This requires extending Input::walkIo().
@@ -547,119 +543,122 @@ bool PathWalker_BR::doWalk(State &s) {
Script *script = findScript(_ch._ani->_scriptName);
script->_nextCommand = script->firstCommand;
}
- return false;
+ return;
}
#endif
- if (_ch._fieldC == 0) {
- _ch._walkPath.erase(_ch._walkPath.begin());
+ if (s._fieldC == 0) {
+ s._walkPath.erase(s._walkPath.begin());
- if (_ch._walkPath.empty()) {
- debugC(3, kDebugWalk, "PathWalker_BR::walk, case 0");
- return true;
+ if (s._walkPath.empty()) {
+ finalizeWalk(s);
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 0");
+ return;
} else {
- debugC(3, kDebugWalk, "PathWalker_BR::walk, moving to next node");
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, moving to next node");
}
}
- _ch._a->getFoot(_ch._startFoot);
+ s._a->getFoot(s._startFoot);
- uint scale = _vm->_location.getScale(_ch._startFoot.y);
+ uint scale = _vm->_location.getScale(s._startFoot.y);
int xStep = (scale * 16) / 100 + 1;
int yStep = (scale * 10) / 100 + 1;
debugC(9, kDebugWalk, "calculated step: (%i, %i)", xStep, yStep);
- _ch._fieldC = 0;
- _ch._step++;
- _ch._step %= 8;
+ s._fieldC = 0;
+ s._step++;
+ s._step %= 8;
int maxX = _vm->_gfx->_backgroundInfo->width;
int minX = 0;
int maxY = _vm->_gfx->_backgroundInfo->height;
int minY = 0;
- int walkFrame = _ch._step;
- _ch._dirFrame = 0;
- Common::Point newpos(_ch._startFoot), delta;
+ int walkFrame = s._step;
+ s._dirFrame = 0;
+ Common::Point newpos(s._startFoot), delta;
- Common::Point p(*_ch._walkPath.begin());
+ Common::Point p(*s._walkPath.begin());
- if (_ch._startFoot.y < p.y && _ch._startFoot.y < maxY && IS_PATH_CLEAR(_ch._startFoot.x, yStep + _ch._startFoot.y)) {
- if (yStep + _ch._startFoot.y <= p.y) {
- _ch._fieldC = 1;
+ if (s._startFoot.y < p.y && s._startFoot.y < maxY && IS_PATH_CLEAR(s._startFoot.x, yStep + s._startFoot.y)) {
+ if (yStep + s._startFoot.y <= p.y) {
+ s._fieldC = 1;
delta.y = yStep;
- newpos.y = yStep + _ch._startFoot.y;
+ newpos.y = yStep + s._startFoot.y;
} else {
- delta.y = p.y - _ch._startFoot.y;
+ delta.y = p.y - s._startFoot.y;
newpos.y = p.y;
}
- _ch._dirFrame = 9;
+ s._dirFrame = 9;
} else
- if (_ch._startFoot.y > p.y && _ch._startFoot.y > minY && IS_PATH_CLEAR(_ch._startFoot.x, _ch._startFoot.y - yStep)) {
- if (_ch._startFoot.y - yStep >= p.y) {
- _ch._fieldC = 1;
+ if (s._startFoot.y > p.y && s._startFoot.y > minY && IS_PATH_CLEAR(s._startFoot.x, s._startFoot.y - yStep)) {
+ if (s._startFoot.y - yStep >= p.y) {
+ s._fieldC = 1;
delta.y = yStep;
- newpos.y = _ch._startFoot.y - yStep;
+ newpos.y = s._startFoot.y - yStep;
} else {
- delta.y = _ch._startFoot.y - p.y;
+ delta.y = s._startFoot.y - p.y;
newpos.y = p.y;
}
- _ch._dirFrame = 0;
+ s._dirFrame = 0;
}
- if (_ch._startFoot.x < p.x && _ch._startFoot.x < maxX && IS_PATH_CLEAR(_ch._startFoot.x + xStep, _ch._startFoot.y)) {
- if (_ch._startFoot.x + xStep <= p.x) {
- _ch._fieldC = 1;
+ if (s._startFoot.x < p.x && s._startFoot.x < maxX && IS_PATH_CLEAR(s._startFoot.x + xStep, s._startFoot.y)) {
+ if (s._startFoot.x + xStep <= p.x) {
+ s._fieldC = 1;
delta.x = xStep;
- newpos.x = xStep + _ch._startFoot.x;
+ newpos.x = xStep + s._startFoot.x;
} else {
- delta.x = p.x - _ch._startFoot.x;
+ delta.x = p.x - s._startFoot.x;
newpos.x = p.x;
}
if (delta.y < delta.x) {
- _ch._dirFrame = 18; // right
+ s._dirFrame = 18; // right
}
} else
- if (_ch._startFoot.x > p.x && _ch._startFoot.x > minX && IS_PATH_CLEAR(_ch._startFoot.x - xStep, _ch._startFoot.y)) {
- if (_ch._startFoot.x - xStep >= p.x) {
- _ch._fieldC = 1;
+ if (s._startFoot.x > p.x && s._startFoot.x > minX && IS_PATH_CLEAR(s._startFoot.x - xStep, s._startFoot.y)) {
+ if (s._startFoot.x - xStep >= p.x) {
+ s._fieldC = 1;
delta.x = xStep;
- newpos.x = _ch._startFoot.x - xStep;
+ newpos.x = s._startFoot.x - xStep;
} else {
- delta.x = _ch._startFoot.x - p.x;
+ delta.x = s._startFoot.x - p.x;
newpos.x = p.x;
}
if (delta.y < delta.x) {
- _ch._dirFrame = 27; // left
+ s._dirFrame = 27; // left
}
}
- debugC(9, kDebugWalk, "foot (%i, %i) dest (%i, %i) deltas = %i/%i ", _ch._startFoot.x, _ch._startFoot.y, p.x, p.y, delta.x, delta.y);
+ debugC(9, kDebugWalk, "foot (%i, %i) dest (%i, %i) deltas = %i/%i ", s._startFoot.x, s._startFoot.y, p.x, p.y, delta.x, delta.y);
- if (_ch._fieldC) {
- debugC(9, kDebugWalk, "PathWalker_BR::walk, foot moved from (%i, %i) to (%i, %i)", _ch._startFoot.x, _ch._startFoot.y, newpos.x, newpos.y);
- _ch._a->setF(walkFrame + _ch._dirFrame + 1);
- _ch._startFoot.x = newpos.x;
- _ch._startFoot.y = newpos.y;
- _ch._a->setFoot(_ch._startFoot);
- _ch._a->setZ(newpos.y);
+ if (s._fieldC) {
+ debugC(9, kDebugWalk, "PathWalker_BR::doWalk, foot moved from (%i, %i) to (%i, %i)", s._startFoot.x, s._startFoot.y, newpos.x, newpos.y);
+ s._a->setF(walkFrame + s._dirFrame + 1);
+ s._startFoot.x = newpos.x;
+ s._startFoot.y = newpos.y;
+ s._a->setFoot(s._startFoot);
+ s._a->setZ(newpos.y);
}
- if (_ch._fieldC || !_ch._walkPath.empty()) {
+ if (s._fieldC || !s._walkPath.empty()) {
Common::Point p;
- _ch._a->getFoot(p);
+ s._a->getFoot(p);
checkTrap(p);
- debugC(3, kDebugWalk, "PathWalker_BR::walk, case 1");
- return false;
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 1");
+ return;
}
- debugC(3, kDebugWalk, "PathWalker_BR::walk, case 2");
- return true;
+ debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 2");
+ finalizeWalk(s);
+ return;
}
-PathWalker_BR::PathWalker_BR() : _ch(_character) {
-
+PathWalker_BR::PathWalker_BR() {
+ _character._active = false;
+ _follower._active = false;
}
diff --git a/engines/parallaction/walk.h b/engines/parallaction/walk.h
index aebfea7975..d746fdec54 100644
--- a/engines/parallaction/walk.h
+++ b/engines/parallaction/walk.h
@@ -102,12 +102,10 @@ class PathWalker_BR {
State _character;
State _follower;
- State &_ch;
-
- void finalizeWalk();
+ void finalizeWalk(State &s);
bool directPathExists(const Common::Point &from, const Common::Point &to);
- void buildPath(uint16 x, uint16 y);
- bool doWalk(State &s);
+ void buildPath(State &s, uint16 x, uint16 y);
+ void doWalk(State &s);
void checkTrap(const Common::Point &p);
public: