aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2004-12-29 21:49:25 +0000
committerAndrew Kurushin2004-12-29 21:49:25 +0000
commit41a5251e28898f4a34ab51c01325d61c2510daf8 (patch)
tree4ccea652e5a4686a15c9bb9f26750deb01cceb52 /saga
parent8cf04e39285216f464ca14afacb74b6b49b0a924 (diff)
downloadscummvm-rg350-41a5251e28898f4a34ab51c01325d61c2510daf8.tar.gz
scummvm-rg350-41a5251e28898f4a34ab51c01325d61c2510daf8.tar.bz2
scummvm-rg350-41a5251e28898f4a34ab51c01325d61c2510daf8.zip
- some work in progress
svn-id: r16375
Diffstat (limited to 'saga')
-rw-r--r--saga/actor.cpp466
-rw-r--r--saga/actor.h30
-rw-r--r--saga/script.h11
-rw-r--r--saga/sfuncs.cpp76
4 files changed, 512 insertions, 71 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp
index f37ddbe799..0efea40548 100644
--- a/saga/actor.cpp
+++ b/saga/actor.cpp
@@ -56,7 +56,7 @@ static int actorCompare(const ActorDataPointer& actor1, const ActorDataPointer&
// Lookup table to convert 8 cardinal directions to 4
int actorDirectectionsLUT[8] = {
ACTOR_DIRECTION_BACK, // kDirUp
- ACTOR_DIRECTION_RIGHT, // kkDirUpRight
+ ACTOR_DIRECTION_RIGHT, // kDirUpRight
ACTOR_DIRECTION_RIGHT, // kDirRight
ACTOR_DIRECTION_RIGHT, // kDirDownRight
ACTOR_DIRECTION_FORWARD,// kDirDown
@@ -76,6 +76,36 @@ PathDirectionData pathDirectionLUT[8][4] = {
{{3, -1, 0}, {0, 0, -1}, {7, -1, -1}}
};
+int pathDirectionLUT2[8][2] = {
+ 0, -1,
+ 1, 0,
+ 0, 1,
+ -1, 0,
+ 1, -1,
+ 1, 1,
+ -1, 1,
+ -1, -1
+};
+
+int angleLUT[16][2] = {
+ 0, -256,
+ 98, -237,
+ 181, -181,
+ 237, -98,
+ 256, 0,
+ 237, 98,
+ 181, 181,
+ 98, 237,
+ 0, 256,
+ -98, 237,
+ -181, 181,
+ -237, 98,
+ -256, 0,
+ -237, -98,
+ -181, -181,
+ -98, -237
+};
+
Actor::Actor(SagaEngine *vm) : _vm(vm) {
int i;
@@ -96,6 +126,7 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_pathCellCount = _yCellCount * _xCellCount;
_pathCell = (int*)malloc(_pathCellCount * sizeof *_pathCell);
+
_pathRect.left = 0;
_pathRect.right = _vm->getDisplayWidth();
_pathRect.top = _vm->getPathYOffset();
@@ -215,6 +246,34 @@ bool Actor::loadActorResources(ActorData * actor) {
return true;
}
+void Actor::realLocation(ActorLocation &location, uint16 objectId, uint16 walkFlags) {
+ int angle;
+ int distance;
+ ActorData *actor;
+ if (walkFlags & kWalkUseAngle) {
+ // tiled stuff
+ if (_vm->_scene->getMode() == SCENE_MODE_ISO) {
+ //todo: it
+ } else {
+ angle = location.x & 15;
+ distance = location.y;
+
+ location.x = (angleLUT[angle][0] * distance) >> 6; //fixme - call real angle calc
+ location.y = (angleLUT[angle][1] * distance) >> 6;
+ }
+ }
+
+ if (objectId != ID_NOTHING) {
+ if (IS_VALID_ACTOR_ID(objectId)) {
+ actor = getActor(objectId);
+ location = actor->location;
+ } else {
+ warning("ObjectId unsupported"); //TODO: do it
+ }
+
+ }
+}
+
ActorData *Actor::getActor(uint16 actorId) {
ActorData *actor;
@@ -1114,7 +1173,7 @@ void Actor::abortSpeech() {
_activeSpeech.playingTime = 0;
}
-void Actor::findActorPath(ActorData * actor, const Point &pointFrom, const Point &pointTo) {
+void Actor::findActorPath(ActorData * actor, const Point &fromPoint, const Point &toPoint) {
Point tempPoint;
Point iteratorPoint;
Point bestPoint;
@@ -1124,11 +1183,11 @@ void Actor::findActorPath(ActorData * actor, const Point &pointFrom, const Point
int i;
Rect intersect;
- tempPoint.y = pointTo.y;
- tempPoint.x = pointTo.x >> 1;
+ tempPoint.y = toPoint.y;
+ tempPoint.x = toPoint.x >> 1;
actor->walkStepsCount = 0;
- if (pointFrom == pointTo) {
+ if (fromPoint == toPoint) {
actor->addWalkPath(tempPoint.x, tempPoint.y);
return;
}
@@ -1165,27 +1224,26 @@ void Actor::findActorPath(ActorData * actor, const Point &pointFrom, const Point
- if (scanPathLine(pointFrom, pointTo)) {
- iteratorPoint.y = pointFrom.y;
- iteratorPoint.x = pointFrom.x >> 1;
+ if (scanPathLine(fromPoint, toPoint)) {
+ iteratorPoint.y = fromPoint.y;
+ iteratorPoint.x = fromPoint.x >> 1;
actor->addWalkPath(iteratorPoint.x, iteratorPoint.y);
actor->addWalkPath(tempPoint.x, tempPoint.y);
return;
}
- i = fillPathArray(pointFrom, pointTo, bestPoint);
+ i = fillPathArray(fromPoint, toPoint, bestPoint);
- if (pointFrom == bestPoint) {
+ if (fromPoint == bestPoint) {
iteratorPoint.y = bestPoint.y;
iteratorPoint.x = bestPoint.x >> 1;
actor->addWalkPath(iteratorPoint.x, iteratorPoint.y);
return;
}
-/*
+
if (i != 0)
- result = SetPath(pcell, from, &bestpoint, nodelist);
-*/
+ setActorPath(actor, fromPoint, bestPoint);
}
bool Actor::scanPathLine(const Point &point1, const Point &point2) {
@@ -1240,9 +1298,9 @@ bool Actor::scanPathLine(const Point &point1, const Point &point2) {
return true;
}
-int Actor::fillPathArray(const Point &pointFrom, const Point &pointTo, Point &bestPoint) {
- Point pathFrom;
- Point pathTo;
+int Actor::fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint) {
+ Point pathFromPoint;
+ Point pathToPoint;
int bestRating;
int currentRating;
Point bestPath;
@@ -1256,24 +1314,24 @@ int Actor::fillPathArray(const Point &pointFrom, const Point &pointTo, Point &be
int directionCount;
- pathFrom.x = pointFrom.x >> 1;
- pathFrom.y = pointFrom.y - _vm->getPathYOffset();
+ pathFromPoint.x = fromPoint.x >> 1;
+ pathFromPoint.y = fromPoint.y - _vm->getPathYOffset();
- pathTo.x = pointTo.x >> 1;
- pathTo.y = pointTo.y - _vm->getPathYOffset();
+ pathToPoint.x = toPoint.x >> 1;
+ pathToPoint.y = toPoint.y - _vm->getPathYOffset();
pointCounter = 0;
- bestRating = quickDistance(pathFrom, pathTo);
- bestPath = pathFrom;
+ bestRating = quickDistance(pathFromPoint, pathToPoint);
+ bestPath = pathFromPoint;
for (startDirection = 0; startDirection < 4; startDirection++) {
newPathDirectionIterator = pathDirectionList.pushBack();
pathDirection = newPathDirectionIterator.operator->();
- pathDirection->x = pathFrom.x;
- pathDirection->y = pathFrom.y;
+ pathDirection->x = pathFromPoint.x;
+ pathDirection->y = pathFromPoint.y;
pathDirection->direction = startDirection;
}
- setPathCell(pathFrom, 0);
+ setPathCell(pathFromPoint, 0);
pathDirectionIterator = pathDirectionList.begin();
@@ -1293,12 +1351,12 @@ int Actor::fillPathArray(const Point &pointFrom, const Point &pointTo, Point &be
pathDirection->y = nextPoint.y;
pathDirection->direction = samplePathDirection->direction;
++pointCounter;
- if (nextPoint == pathTo) {
- bestPoint.x = pointTo.x & ~1;
- bestPoint.y = pointTo.y;
+ if (nextPoint == pathToPoint) {
+ bestPoint.x = toPoint.x & ~1;
+ bestPoint.y = toPoint.y;
return pointCounter;
}
- currentRating = quickDistance(nextPoint, pathTo);
+ currentRating = quickDistance(nextPoint, pathToPoint);
if (currentRating < bestRating) {
bestRating = currentRating;
bestPath = nextPoint;
@@ -1314,6 +1372,356 @@ int Actor::fillPathArray(const Point &pointFrom, const Point &pointTo, Point &be
return pointCounter;
}
+void Actor::setActorPath(ActorData * actor, const Point &fromPoint, const Point &toPoint) {
+ Point pathFromPoint;
+ Point pathToPoint;
+ Point *point;
+ Point nextPoint;
+ int direction;
+ PathNode *node;
+ int i, last;
+
+ pathFromPoint.x = fromPoint.x >> 1;
+ pathFromPoint.y = fromPoint.y - _vm->getPathYOffset();
+
+ pathToPoint.x = toPoint.x >> 1;
+ pathToPoint.y = toPoint.y - _vm->getPathYOffset();
+
+
+
+ _pathList[0].x = pathToPoint.x;
+ _pathList[0].y = toPoint.y;
+ nextPoint = pathToPoint;
+ _pathListIndex = 0;
+
+ point = _pathList;
+ while ( !(nextPoint == pathFromPoint)) {
+ _pathListIndex++;
+ if (_pathListIndex >= PATH_LIST_MAX) {
+ error("Actor::setActorPath PATH_LIST_MAX");
+ }
+ point++;
+ direction = getPathCell(nextPoint);
+ nextPoint.x -= pathDirectionLUT2[direction][0];
+ nextPoint.y -= pathDirectionLUT2[direction][1];
+ point->x = nextPoint.x;
+ point->y = nextPoint.y + _vm->getPathYOffset();
+ }
+
+ pathToNode();
+
+ removeNodes();
+
+ nodeToPath();
+
+ removePathPoints();
+
+ _pathNodeIndex++;
+ last = min(_pathNodeIndex, PATH_NODE_MAX);
+ for (i = 0, node = _pathNodeList; i < last; i++, node++) {
+ actor->addWalkPath(node->x, node->y);
+ }
+
+}
+
+void Actor::pathToNode() {
+ Point point1, point2, delta;
+ int direction;
+ int i;
+ WORD nodeindex = 0;
+ Point *point;
+ PathNode *nodeList;
+
+ _pathNodeIndex = 0;
+ point= &_pathList[_pathListIndex];
+ direction = 0,
+
+ _pathNodeList->x = point->x;
+ _pathNodeList->y = point->y;
+ nodeList = _pathNodeList;
+
+ for (i = _pathListIndex; i > 0; i--) {
+ point1 = *point;
+ --point;
+ point2 = *point;
+ if (direction == 0) {
+ delta.x = integerCompare(point2.x, point1.x);
+ delta.y = integerCompare(point2.y, point1.y);
+ direction++;
+ }
+ if ((point1.x + delta.x != point2.x) || (point1.y + delta.y != point2.y)) {
+ ++nodeList;
+ ++_pathNodeIndex;
+ nodeList->x = point1.x;
+ nodeList->y = point2.x;
+ direction--;
+ i++;
+ point++;
+ }
+ }
+ ++nodeList;
+ ++_pathNodeIndex;
+ nodeList->x = _pathList->x;
+ nodeList->y = _pathList->y;
+}
+
+int pathLine(Point *pointList, const Point &point1, const Point &point2) {
+ Point point;
+ Point delta;
+ Point tempPoint;
+ int s1;
+ int s2;
+ bool interchange = false;
+ int errterm;
+ int i;
+
+ delta.x = abs(point2.x - point1.x);
+ delta.y = abs(point2.y - point1.y);
+ point = point1;
+ s1 = integerCompare(point2.x, point1.x);
+ s2 = integerCompare(point2.y, point1.y);
+
+ if (delta.y > delta.x) {
+ SWAP(delta.y, delta.x);
+ interchange = true;
+ }
+
+ tempPoint.x = delta.x * 2;
+ tempPoint.y = delta.y * 2;
+
+ errterm = tempPoint.y - delta.x;
+
+ for (i = 0; i < delta.x; i++) {
+ while (errterm >= 0) {
+ if (interchange) {
+ point.x += s1;
+ } else {
+ point.y += s2;
+ }
+ errterm -= tempPoint.x;
+ }
+ if (interchange) {
+ point.y += s2;
+ } else {
+ point.x += s1;
+ }
+ errterm += tempPoint.y;
+
+ pointList[i] = point;
+ }
+ return delta.x;
+}
+
+void Actor::nodeToPath() {
+ int i;
+ Point point1, point2;
+ PathNode *node;
+ Point *point;
+
+ for (i = 0, point = _pathList; i < PATH_LIST_MAX; i++, point++) {
+ point->x = point->y = PATH_NODE_EMPTY;
+ }
+
+ _pathListIndex = 1;
+ _pathList[0].x = _pathNodeList[0].x;
+ _pathList[0].y = _pathNodeList[0].y;
+ _pathNodeList[0].link = 0;
+ for (i = 0, node = _pathNodeList; i < _pathNodeIndex; i++) {
+ point1.x = node->x;
+ point1.y = node->y;
+ node++;
+ point2.x = node->x;
+ point2.y = node->y;
+ _pathListIndex += pathLine(&_pathList[_pathListIndex], point1, point2);
+ node->link = _pathListIndex - 1;
+ }
+ _pathListIndex--;
+ _pathNodeList[_pathNodeIndex].link = _pathListIndex;
+
+}
+
+void Actor::removeNodes() {
+ int i, j, k;
+ PathNode *iNode, *jNode, *kNode, *fNode;
+ Point point1, point2;
+ fNode = &_pathNodeList[_pathNodeIndex];
+
+ point1.x = _pathNodeList[0].x * 2;
+ point1.y = _pathNodeList[0].y;
+ point2.x = fNode->x * 2;
+ point2.y = fNode->y;
+
+ if (scanPathLine(point1, point2)) {
+ _pathNodeList[1] = *fNode;
+ _pathNodeIndex = 1;
+ }
+
+ if (_pathNodeIndex < 4) {
+ return;
+ }
+
+ for (i = _pathNodeIndex - 1, iNode = fNode-1; i > 1 ; i--, iNode--) {
+ if (iNode->x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ point1.x = _pathNodeList[0].x * 2;
+ point1.y = _pathNodeList[0].y;
+ point2.x = iNode->x * 2;
+ point2.y = iNode->y;
+
+ if (scanPathLine(point1, point2)) {
+ for (j = 1, jNode = _pathNodeList + 1; j < i; j++, jNode++) {
+ jNode->x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+
+ for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeIndex - 1; i++, iNode++) {
+ if (iNode->x == PATH_NODE_EMPTY) {
+ continue;
+ }
+ point1.x = fNode->x * 2;
+ point1.y = fNode->y;
+ point2.x = iNode->x * 2;
+ point2.y = iNode->y;
+
+ if (scanPathLine(point1, point2)) {
+ for (j = i + 1, jNode = iNode + 1; j < _pathNodeIndex; j++, jNode++) {
+ jNode->x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+ condenseNodeList();
+
+ for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeIndex - 1; i++, iNode++) {
+ if (iNode->x == PATH_NODE_EMPTY) {
+ continue;
+ }
+ for (j = i + 2,jNode = iNode + 2; j < _pathNodeIndex; j++, jNode++)
+ {
+ if (jNode->x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ point1.x = iNode->x * 2;
+ point1.y = iNode->y;
+ point2.x = jNode->x * 2;
+ point2.y = jNode->y;
+
+ if (scanPathLine(point1, point2)) {
+ for (k = i + 1,kNode = iNode + 1; k < j; k++, kNode++) {
+ kNode->x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+ }
+ condenseNodeList();
+}
+
+void Actor::condenseNodeList() {
+ int i, j, count;
+ PathNode *iNode, *jNode;
+
+ count = _pathNodeIndex;
+
+ for (i = 1, iNode = _pathNodeList+1; i < _pathNodeIndex; i++, iNode++) {
+ if (iNode->x == PATH_NODE_EMPTY) {
+ j = i + 1;
+ jNode = iNode + 1;
+ while ( jNode->x == PATH_NODE_EMPTY ) {
+ j++;
+ jNode++;
+ }
+ *iNode = *jNode;
+ count = i;
+ jNode->x = PATH_NODE_EMPTY;
+ if (j == _pathNodeIndex) {
+ break;
+ }
+ }
+ }
+ _pathNodeIndex = count;
+}
+
+void Actor::removePathPoints() {
+ int i, j, k, l;
+ PathNode *node;
+ int newPathNodeIndex;
+ int start;
+ int end;
+ Point point1, point2, point3, point4;
+
+
+ if (_pathNodeIndex < 2)
+ return;
+
+
+ _newPathNodeList[0] = _pathNodeList[0];
+ newPathNodeIndex = 0;
+
+ for (i = 1, node = _pathNodeList + 1; i < _pathNodeIndex; i++, node++) {
+ newPathNodeIndex++;
+ _newPathNodeList[newPathNodeIndex] = *node;
+
+ for (j = 5; j > 0; j--) {
+ start = node->link - j;
+ end = node->link + j;
+
+ if (start < 0 || end > _pathListIndex) {
+ continue;
+ }
+
+ point1.x = _pathList[start].x;
+ if (point1.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+ point2.x = _pathList[end].x;
+ if (point2.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ point1.y = _pathList[start].y;
+ point2.y = _pathList[end].y;
+
+ point3.x = point1.x * 2;
+ point3.y = point1.y;
+ point4.x = point2.x * 2;
+ point4.y = point2.y;
+ if (scanPathLine( point3, point4)) {
+ for (l = 1; l <= newPathNodeIndex; l++) {
+ if (start <= _newPathNodeList[l].link) {
+ newPathNodeIndex = l;
+ _newPathNodeList[newPathNodeIndex].x = point1.x;
+ _newPathNodeList[newPathNodeIndex].y = point1.y;
+ _newPathNodeList[newPathNodeIndex].link = start;
+ newPathNodeIndex++;
+ break;
+ }
+ }
+ _newPathNodeList[newPathNodeIndex].x = point2.x;
+ _newPathNodeList[newPathNodeIndex].y = point2.y;
+ _newPathNodeList[newPathNodeIndex].link = end;
+
+ for (k = start + 1; k < end; k++) {
+ _pathList[k].x = PATH_NODE_EMPTY;
+ }
+ break;
+ }
+ }
+ }
+
+ newPathNodeIndex++;
+ _newPathNodeList[newPathNodeIndex] = _pathNodeList[_pathNodeIndex];
+
+ for (i = 0, j = 0; i <= newPathNodeIndex; i++) {
+ if (newPathNodeIndex == i || (_newPathNodeList[i].y != _newPathNodeList[i+1].y
+ || _newPathNodeList[i].x != _newPathNodeList[i+1].x) )
+ _pathNodeList[j++] = _newPathNodeList[i];
+ }
+ _pathNodeIndex = j - 1;
+}
+
/*
// Console wrappers - must be safe to run
// TODO - checkup ALL arguments, cause wrong arguments may fall function with "error"
diff --git a/saga/actor.h b/saga/actor.h
index 60e5de9f3f..4ab3f07efe 100644
--- a/saga/actor.h
+++ b/saga/actor.h
@@ -53,6 +53,12 @@ namespace Saga {
#define ACTOR_SPEECH_STRING_MAX 16 // speech const
#define ACTOR_SPEECH_ACTORS_MAX 8
+#define PATH_NODE_MAX 100
+#define PATH_LIST_MAX 500
+
+#define PATH_NODE_EMPTY -1
+
+
#define ID_NOTHING 0
#define ID_PROTAG 1
@@ -124,6 +130,12 @@ struct PathDirectionData {
typedef SortedList<PathDirectionData> PathDirectionList;
+struct PathNode {
+ int x;
+ int y;
+ int link;
+};
+
struct ActorFrameRange {
int frameIndex;
int frameCount;
@@ -259,6 +271,7 @@ public:
bool actorWalkTo(uint16 actorId, const ActorLocation &toLocation);
ActorData *getActor(uint16 actorId);
ActorFrameRange *getActorFrameRange(uint16 actorId, int frameType);
+ void realLocation(ActorLocation &location, uint16 objectId, uint16 walkFlags);
// speech
void actorSpeech(uint16 actorId, const char **strings, int stringsCount, uint16 sampleResourceId, int speechFlags);
@@ -280,7 +293,7 @@ private:
void createDrawOrderList();
void calcActorScreenPosition(ActorData * actor);
bool followProtagonist(ActorData * actor);
- void findActorPath(ActorData * actor, const Point &pointFrom, const Point &pointTo);
+ void findActorPath(ActorData * actor, const Point &fromPoint, const Point &toPoint);
void handleSpeech(int msec);
void handleActions(int msec, bool setup);
void setPathCell(const Point &testPoint, int value) {
@@ -290,7 +303,13 @@ private:
return _pathCell[testPoint.x + testPoint.y * _xCellCount];
}
bool scanPathLine(const Point &point1, const Point &point2);
- int fillPathArray(const Point &pointFrom, const Point &pointTo, Point &bestPoint);
+ int fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint);
+ void setActorPath(ActorData * actor, const Point &fromPoint, const Point &toPoint);
+ void pathToNode();
+ void condenseNodeList();
+ void removeNodes();
+ void nodeToPath();
+ void removePathPoints();
int _lastTickMsec;
SagaEngine *_vm;
@@ -298,6 +317,8 @@ private:
ActorOrderList _drawOrderList;
ActorData _actors[ACTORCOUNT];
SpeechData _activeSpeech;
+
+//path stuff
Rect _barrierList[ACTOR_BARRIERS_MAX];
int _barrierCount;
int *_pathCell;
@@ -305,6 +326,11 @@ private:
int _xCellCount;
int _yCellCount;
Rect _pathRect;
+ Point _pathList[PATH_LIST_MAX];
+ int _pathListIndex;
+ PathNode _pathNodeList[PATH_NODE_MAX];
+ PathNode _newPathNodeList[PATH_NODE_MAX];
+ int _pathNodeIndex;
};
diff --git a/saga/script.h b/saga/script.h
index 804b311150..0808f7fb6b 100644
--- a/saga/script.h
+++ b/saga/script.h
@@ -114,6 +114,13 @@ enum CycleFlags {
kCycleReverse = (1 << 3)
};
+enum WalkFlags {
+ kWalkBackPedal = (1<<0),
+ kWalkAsync = (1<<1),
+ kWalkUseAngle = (1<<2),
+ kWalkFace = (1<<5)
+};
+
struct SCRIPT_THREAD {
int flags; // ThreadFlags
int waitType; // ThreadWaitTypes
@@ -325,7 +332,7 @@ private:
int SF_cycleColors(SCRIPTFUNC_PARAMS);
int sfDoCenterActor(SCRIPTFUNC_PARAMS);
int sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS);
- int SF_actorWalkToAsync(SCRIPTFUNC_PARAMS);
+ int sfScriptWalkToAsync(SCRIPTFUNC_PARAMS);
int SF_enableZone(SCRIPTFUNC_PARAMS);
int sfSetActorState(SCRIPTFUNC_PARAMS);
int scriptMoveTo(SCRIPTFUNC_PARAMS);
@@ -334,7 +341,7 @@ private:
int sfFinishBgdAnim(SCRIPTFUNC_PARAMS);
int sfSwapActors(SCRIPTFUNC_PARAMS);
int sfSimulSpeech(SCRIPTFUNC_PARAMS);
- int SF_actorWalk(SCRIPTFUNC_PARAMS);
+ int sfScriptWalk(SCRIPTFUNC_PARAMS);
int sfCycleFrames(SCRIPTFUNC_PARAMS);
int sfSetFrame(SCRIPTFUNC_PARAMS);
int SF_setRightPortrait(SCRIPTFUNC_PARAMS);
diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp
index 805801fa8b..e5a74aefea 100644
--- a/saga/sfuncs.cpp
+++ b/saga/sfuncs.cpp
@@ -74,7 +74,7 @@ void Script::setupScriptFuncList(void) {
OPCODE(SF_cycleColors),
OPCODE(sfDoCenterActor),
OPCODE(sfStartBgdAnimSpeed),
- OPCODE(SF_actorWalkToAsync),
+ OPCODE(sfScriptWalkToAsync),
OPCODE(SF_enableZone),
OPCODE(sfSetActorState),
OPCODE(scriptMoveTo),
@@ -83,7 +83,7 @@ void Script::setupScriptFuncList(void) {
OPCODE(sfFinishBgdAnim),
OPCODE(sfSwapActors),
OPCODE(sfSimulSpeech),
- OPCODE(SF_actorWalk),
+ OPCODE(sfScriptWalk),
OPCODE(sfCycleFrames),
OPCODE(sfSetFrame),
OPCODE(SF_setRightPortrait),
@@ -197,7 +197,6 @@ int Script::SF_commandMode(SCRIPTFUNC_PARAMS) {
}
// Script function #6 (0x06) blocking
-// Commands the specified actor to walk to the given position
// Param1: actor id
// Param2: actor x
// Param3: actor y
@@ -478,28 +477,24 @@ int Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
}
// Script function #27 (0x1B) nonblocking
-// Commands the specified actor to walk to the given position
// Param1: actor id
-// Param2: actor destination x
-// Param3: actor destination y
-int Script::SF_actorWalkToAsync(SCRIPTFUNC_PARAMS) {
- ScriptDataWord actor_parm;
- ScriptDataWord x_parm;
- ScriptDataWord y_parm;
+// Param2: actor x
+// Param3: actor y
+int Script::sfScriptWalkToAsync(SCRIPTFUNC_PARAMS) {
uint16 actorId;
- Point pt;
-
- actor_parm = thread->pop();
+ ActorLocation actorLocation;
+ ActorData *actor;
- x_parm = thread->pop();
- y_parm = thread->pop();
+ actorId = getSWord(thread->pop());
+ actorLocation.x = getSWord(thread->pop());
+ actorLocation.y = getSWord(thread->pop());
- actorId = getSWord(actor_parm);
+ actor = _vm->_actor->getActor(actorId);
+ actorLocation.z = actor->location.z;
- pt.x = getSWord(x_parm);
- pt.y = getSWord(y_parm);
-// error("!");
+ actor->flags &= ~kFollower;
+ _vm->_actor->actorWalkTo(actorId, actorLocation);
return SUCCESS;
}
@@ -666,32 +661,37 @@ int Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
}
// Script function #36 (0x24) ?
-// Commands the specified actor to walk to the given position
// Param1: actor id
-// Param2: actor destination x
-// Param3: actor destination y
-// Param4: flags telling how to walk
-int Script::SF_actorWalk(SCRIPTFUNC_PARAMS) {
- // INCOMPLETE
- ScriptDataWord actor_parm;
- ScriptDataWord x_parm;
- ScriptDataWord y_parm;
- ScriptDataWord flags_parm;
+// Param2: actor x
+// Param3: actor y
+// Param4: actor walk flag
+int Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
uint16 actorId;
- Point pt;
+ ActorLocation actorLocation;
+ ActorData *actor;
+ uint16 walkFlags;
- actor_parm = thread->pop();
- x_parm = thread->pop();
- y_parm = thread->pop();
- flags_parm = thread->pop();
+ actorId = getSWord(thread->pop());
+ actorLocation.x = getSWord(thread->pop());
+ actorLocation.y = getSWord(thread->pop());
+ walkFlags = getUWord(thread->pop());
- actorId = getSWord(actor_parm);
+ actor = _vm->_actor->getActor(actorId);
+ actorLocation.z = actor->location.z;
- pt.x = getSWord(x_parm);
- pt.y = getSWord(y_parm);
+ _vm->_actor->realLocation(actorLocation, ID_NOTHING, walkFlags);
-// error("!");
+ actor->flags &= ~kFollower;
+
+ if (_vm->_actor->actorWalkTo(actorId, actorLocation) && !(walkFlags & kWalkAsync)) {
+ thread->waitWalk(actor);
+ }
+
+ if (walkFlags & kWalkBackPedal) {
+ actor->actorFlags |= kActorBackwards;
+ }
+ actor->actorFlags = (actor->actorFlags & ~kActorFacingMask) | (walkFlags & kActorFacingMask);
return SUCCESS;
}