aboutsummaryrefslogtreecommitdiff
path: root/engines/fullpipe/motion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/fullpipe/motion.cpp')
-rw-r--r--engines/fullpipe/motion.cpp1027
1 files changed, 972 insertions, 55 deletions
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
index f67011a50f..9171dc1405 100644
--- a/engines/fullpipe/motion.cpp
+++ b/engines/fullpipe/motion.cpp
@@ -28,9 +28,9 @@
#include "fullpipe/objects.h"
#include "fullpipe/statics.h"
+#include "fullpipe/gameloader.h"
#include "fullpipe/motion.h"
#include "fullpipe/messages.h"
-#include "fullpipe/gameloader.h"
namespace Fullpipe {
@@ -42,6 +42,48 @@ bool MotionController::load(MfcArchive &file) {
return true;
}
+void MotionController::enableLinks(const char *linkName, bool enable) {
+ warning("STUB: MotionController::enableLinks()");
+}
+
+MovGraphLink *MotionController::getLinkByName(const char *name) {
+ if (_objtype == kObjTypeMctlCompound) {
+ MctlCompound *obj = (MctlCompound *)this;
+
+ for (uint i = 0; i < obj->getMotionControllerCount(); i++) {
+ MotionController *con = obj->getMotionController(i);
+
+ if (con->_objtype == kObjTypeMovGraph) {
+ MovGraph *gr = (MovGraph *)con;
+
+ for (ObList::iterator l = gr->_links.begin(); l != gr->_links.end(); ++l) {
+ assert(((CObject *)*l)->_objtype == kObjTypeMovGraphLink);
+
+ MovGraphLink *lnk = (MovGraphLink *)*l;
+
+ if (!strcmp(lnk->_name, name))
+ return lnk;
+ }
+ }
+ }
+ }
+
+ if (_objtype == kObjTypeMovGraph) {
+ MovGraph *gr = (MovGraph *)this;
+
+ for (ObList::iterator l = gr->_links.begin(); l != gr->_links.end(); ++l) {
+ assert(((CObject *)*l)->_objtype == kObjTypeMovGraphLink);
+
+ MovGraphLink *lnk = (MovGraphLink *)*l;
+
+ if (!strcmp(lnk->_name, name))
+ return lnk;
+ }
+ }
+
+ return 0;
+}
+
bool MctlCompound::load(MfcArchive &file) {
debug(5, "MctlCompound::load()");
@@ -168,9 +210,9 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos,
if (mq) {
for (uint i = 0; i < closestP->_messageQueueObj->getCount(); i++) {
- ex = new ExCommand(closestP->_messageQueueObj->getExCommandByIndex(i));
+ ex = closestP->_messageQueueObj->getExCommandByIndex(i)->createClone();
ex->_excFlags |= 2;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
}
ex = new ExCommand(subj->_id, 51, 0, xpos, ypos, 0, 1, 0, 0, 0);
@@ -179,18 +221,201 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos,
ex->_keyCode = subj->_okeyCode;
ex->_excFlags |= 2;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
}
return mq;
}
+MctlCompoundArrayItem::~MctlCompoundArrayItem() {
+ delete _movGraphReactObj;
+ delete _motionControllerObj;
+}
+
+MctlLadder::MctlLadder() {
+ _width = 0;
+ _ladderX = 0;
+ _height = 0;
+ _ladderY = 0;
+ _ladder_field_14 = 0;
+
+ _ladder_field_20 = 0;
+ _ladder_field_24 = 0;
+}
+
+MctlLadder::~MctlLadder() {
+ freeItems();
+}
+
+int MctlLadder::collisionDetection(StaticANIObject *man) {
+ if (findObjectPos(man) < 0)
+ return 0;
+
+ double delta;
+
+ if ((double)(man->_oy - _ladderY) / (double)_height < 0.0)
+ delta = -0.5;
+ else
+ delta = 0.5;
+
+ int res = (int)((double)(man->_oy - _ladderY) / (double)_height + delta);
+
+ if (res < 0)
+ return 0;
+
+ return res;
+}
+
+void MctlLadder::addObject(StaticANIObject *obj) {
+ if (findObjectPos(obj) < 0) {
+ MctlLadderMovement *movement = new MctlLadderMovement;
+
+ if (initMovement(obj, movement)) {
+ _mgm.addItem(obj->_id);
+ _movements.push_back(movement);
+ } else {
+ delete movement;
+ }
+ }
+}
+
+int MctlLadder::findObjectPos(StaticANIObject *obj) {
+ int res = -1;
+
+ for (Common::List<MctlLadderMovement *>::iterator it = _movements.begin(); it != _movements.end(); ++it, ++res)
+ if ((*it)->objId == obj->_id)
+ break;
+
+ return res;
+}
+
+bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement) {
+ GameVar *v = g_fp->getGameLoaderGameVar()->getSubVarByName(ani->getName());
+
+ if (!v)
+ return false;
+
+ v = v->getSubVarByName("Test_Ladder");
+
+ if (!v)
+ return false;
+
+ movement->staticIdsSize = 6;
+ movement->movVars = new MctlLadderMovementVars;
+ movement->staticIds = new int[movement->staticIdsSize];
+
+ v = v->getSubVarByName("Up");
+
+ if (!v)
+ return false;
+
+ movement->movVars->varUpStart = v->getSubVarAsInt("Start");
+ movement->movVars->varUpGo = v->getSubVarAsInt("Go");
+ movement->movVars->varUpStop = v->getSubVarAsInt("Stop");
+
+ movement->staticIds[0] = ani->getMovementById(movement->movVars->varUpStart)->_staticsObj1->_staticsId;
+ movement->staticIds[2] = ani->getMovementById(movement->movVars->varUpGo)->_staticsObj1->_staticsId;
+
+ v = v->getSubVarByName("Down");
+
+ if (!v)
+ return false;
+
+ movement->movVars->varDownStart = v->getSubVarAsInt("Start");
+ movement->movVars->varDownGo = v->getSubVarAsInt("Go");
+ movement->movVars->varDownStop = v->getSubVarAsInt("Stop");
+
+ movement->staticIds[1] = ani->getMovementById(movement->movVars->varDownStart)->_staticsObj1->_staticsId;
+ movement->staticIds[3] = ani->getMovementById(movement->movVars->varDownGo)->_staticsObj1->_staticsId;
+
+ movement->objId = ani->_id;
+
+ return true;
+}
+
+void MctlLadder::freeItems() {
+ _mgm.clear();
+
+ for (Common::List<MctlLadderMovement *>::iterator it = _movements.begin(); it != _movements.end(); ++it) {
+ delete (*it)->movVars;
+ delete [] (*it)->staticIds;
+ }
+
+ _movements.clear();
+}
+
+MessageQueue *MctlLadder::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ MessageQueue *mq = doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId);
+
+ if (mq) {
+ if (mq->chain(subj))
+ return mq;
+ }
+
+ return 0;
+}
+
+MessageQueue *MctlLadder::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+ warning("STUB: MctlLadder::doWalkTo()");
+
+ return 0;
+}
+
+MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) {
+ return doWalkTo(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0);
+}
+
MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr) {
warning("STUB: MctlCompound::findClosestConnectionPoint()");
return 0;
}
+void MctlCompound::replaceNodeX(int from, int to) {
+ warning("STUB: MctlCompound::replaceNodeX()");
+}
+
+MctlConnectionPoint::MctlConnectionPoint() {
+ _connectionX = 0;
+ _connectionY = 0;
+ _field_C = 0;
+ _field_10 = 0;
+ _field_14 = 0;
+ _field_16 = 0;
+ _messageQueueObj = 0;
+ _motionControllerObj = 0;
+}
+
+MctlConnectionPoint::~MctlConnectionPoint() {
+ delete _messageQueueObj;
+}
+
+MovInfo1::MovInfo1(MovInfo1 *src) {
+ index = src->index;
+ pt1 = src->pt1;
+ pt2 = src->pt2;
+ distance1 = src->distance1;
+ distance2 = src->distance2;
+ subIndex = src->subIndex;
+ item1Index = src->item1Index;
+ items = src->items;
+ itemsCount = src->itemsCount;
+ flags = src->flags;
+}
+
+void MovInfo1::clear() {
+ index = 0;
+ pt1.x = pt1.y = 0;
+ pt2.x = pt2.y = 0;
+ distance1 = 0;
+ distance2 = 0;
+ subIndex = 0;
+ item1Index = 0;
+ items.clear();
+ itemsCount = 0;
+ flags = 0;
+}
+
bool MctlCompoundArray::load(MfcArchive &file) {
debug(5, "MctlCompoundArray::load()");
@@ -238,6 +463,10 @@ MovGraph::MovGraph() {
_objtype = kObjTypeMovGraph;
}
+MovGraph::~MovGraph() {
+ warning("STUB: MovGraph::~MovGraph()");
+}
+
bool MovGraph::load(MfcArchive &file) {
debug(5, "MovGraph::load()");
@@ -280,10 +509,9 @@ int MovGraph::method28() {
return 0;
}
-int MovGraph::method2C() {
- warning("STUB: MovGraph::method2C()");
-
- return 0;
+int MovGraph::method2C(StaticANIObject *obj, int x, int y) {
+ obj->setOXY(x, y);
+ return method3C(obj, 1);
}
MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
@@ -298,7 +526,7 @@ int MovGraph::changeCallback() {
return 0;
}
-int MovGraph::method3C() {
+int MovGraph::method3C(StaticANIObject *ani, int flag) {
warning("STUB: MovGraph::method3C()");
return 0;
@@ -351,8 +579,8 @@ double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzz
return -1.0;
}
} else {
- point->x = n1x + (dist2x * distm / link->_distance);
- point->y = n1y + (dist2y * distm / link->_distance);
+ point->x = (int)(n1x + (dist2x * distm / link->_distance));
+ point->y = (int)(n1y + (dist2y * distm / link->_distance));
}
return res;
@@ -405,7 +633,7 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
item->_obj = obj;
item->_objectId = obj->_id;
- GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(obj->_objectName);
+ GameVar *var = g_fp->getGameLoaderGameVar()->getSubVarByName(obj->_objectName);
if (!var)
return false;
@@ -658,15 +886,13 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL
}
MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
- MovInfo1 movinfo;
-
- memcpy(&movinfo, movInfo, sizeof(movinfo));
+ MovInfo1 movinfo(movInfo);
int curX = movInfo->pt1.x;
int curY = movInfo->pt1.y;
int curDistance = movInfo->distance1;
- MessageQueue *mq = new MessageQueue(g_fullpipe->_globalMessageQueueList->compact());
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
for (int i = 0; i < movInfo->itemsCount - 1; i++) {
if (movInfo->items[i + 1]->subIndex != 10) {
@@ -674,10 +900,10 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
if (i >= movInfo->itemsCount - 2 || movInfo->items[i + 2]->subIndex != 10) {
movinfo.flags = 0;
- mg2i = &_items2[movInfo->field_0]->_subItems[movInfo->items[i]->subIndex]._turnS[movInfo->items[i + 1]->subIndex];
+ mg2i = &_items2[movInfo->index]->_subItems[movInfo->items[i]->subIndex]._turnS[movInfo->items[i + 1]->subIndex];
} else {
movinfo.flags = 2;
- mg2i = &_items2[movInfo->field_0]->_subItems[movInfo->items[i]->subIndex]._turn[movInfo->items[i + 1]->subIndex];
+ mg2i = &_items2[movInfo->index]->_subItems[movInfo->items[i]->subIndex]._turn[movInfo->items[i + 1]->subIndex];
}
if (i < movInfo->itemsCount - 2
|| (movInfo->items[i]->x == movInfo->items[i + 1]->x
@@ -687,13 +913,13 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
|| movInfo->items[i + 1]->x == -1
|| movInfo->items[i + 1]->y == -1) {
- ExCommand *ex = new ExCommand(_items2[movInfo->field_0]->_objectId, 1, mg2i->_movementId, 0, 0, 0, 1, 0, 0, 0);
+ ExCommand *ex = new ExCommand(_items2[movInfo->index]->_objectId, 1, mg2i->_movementId, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags |= 2;
- ex->_keyCode = _items2[movInfo->field_0]->_obj->_okeyCode;
+ ex->_keyCode = _items2[movInfo->index]->_obj->_okeyCode;
ex->_field_24 = 1;
ex->_field_14 = -1;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
curX += mg2i->_mx;
curY += mg2i->_my;
@@ -702,7 +928,7 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
memset(&mgminfo, 0, sizeof(mgminfo));
- mgminfo.ani = _items2[movInfo->field_0]->_obj;
+ mgminfo.ani = _items2[movInfo->index]->_obj;
mgminfo.staticsId2 = mg2i->_mov->_staticsObj2->_staticsId;
mgminfo.x1 = movInfo->items[i + 1]->x;
mgminfo.y1 = movInfo->items[i + 1]->y;
@@ -745,13 +971,13 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
|| movInfo->items[i + 2]->subIndex == movInfo->items[i + 3]->subIndex) {
movinfo.flags &= 3;
} else {
- MG2I *m = &_items2[movInfo->field_0]->_subItems[movInfo->items[i + 2]->subIndex]._turnS[movInfo->items[i + 3]->subIndex];
+ MG2I *m = &_items2[movInfo->index]->_subItems[movInfo->items[i + 2]->subIndex]._turnS[movInfo->items[i + 3]->subIndex];
movinfo.pt2.x -= m->_mx;
movinfo.pt2.y -= m->_my;
movinfo.flags &= 3;
}
} else {
- MG2I *m = &_items2[movInfo->field_0]->_subItems[movInfo->items[i + 2]->subIndex]._turn[movInfo->items[i + 3]->subIndex];
+ MG2I *m = &_items2[movInfo->index]->_subItems[movInfo->items[i + 2]->subIndex]._turn[movInfo->items[i + 3]->subIndex];
if (movinfo.item1Index && movinfo.item1Index != 1) {
movinfo.pt2.y -= m->_my;
@@ -902,7 +1128,7 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
}
if (obj->_ox == xpos && obj->_oy == ypos) {
- g_fullpipe->_globalMessageQueueList->compact();
+ g_fp->_globalMessageQueueList->compact();
MessageQueue *mq = new MessageQueue();
@@ -922,20 +1148,20 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
ex->_keyCode = picAniInfo.field_8;
ex->_excFlags |= 2;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
} else {
ExCommand *ex = new ExCommand(picAniInfo.objectId, 22, obj->_statics->_staticsId, 0, 0, 0, 1, 0, 0, 0);
ex->_keyCode = picAniInfo.field_8;
ex->_excFlags |= 3;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
ex = new ExCommand(picAniInfo.objectId, 5, -1, obj->_ox, obj->_oy, 0, 1, 0, 0, 0);
ex->_field_14 = -1;
ex->_keyCode = picAniInfo.field_8;
ex->_excFlags |= 3;
- mq->_exCommands.push_back(ex);
+ mq->addExCommandToEnd(ex);
}
obj->setPicAniInfo(&picAniInfo);
@@ -979,7 +1205,7 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
if (minPath < 0.0 || ((linkInfoSource.node != linkInfoDest.node || !linkInfoSource.node) && !tempLinkList.size()))
return 0;
- memset(&movInfo1, 0, sizeof(movInfo1));
+ movInfo1.clear();
movInfo1.subIndex = idxsub;
movInfo1.pt1.x = obj->_ox;
@@ -1010,7 +1236,7 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
double dst1 = sqrt((double)((ypos - nod->_y) * (ypos - nod->_y) + (xpos - nod->_x) * (xpos - nod->_x)));
int dst = linkInfoDest.link->_movGraphNode2->_distance - nod->_distance;
- movInfo1.distance2 = nod->_distance + (dst1 * (double)dst / linkInfoDest.link->_distance);
+ movInfo1.distance2 = (int)(nod->_distance + (dst1 * (double)dst / linkInfoDest.link->_distance));
calcDistance(&movInfo1.pt2, linkInfoDest.link, 1);
@@ -1157,10 +1383,205 @@ int MovGraph2::findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common
return node3->_x >= node2->_x;
}
-MessageQueue *MovGraph2::genMovement(MovInfo1 *movinfo) {
- warning("STUB: MovGraph2::genMovement()");
+MessageQueue *MovGraph2::genMovement(MovInfo1 *info) {
+ int mx1 = 0;
+ int my1 = 0;
- return 0;
+ if (!(info->flags & 2)) {
+ mx1 = _items2[info->index]->_subItems[info->subIndex]._walk[0]._mx;
+ my1 = _items2[info->index]->_subItems[info->subIndex]._walk[0]._my;
+ }
+
+ int mx2 = 0;
+ int my2 = 0;
+
+ if (!(info->flags & 4)) {
+ mx2 = _items2[info->index]->_subItems[info->subIndex]._walk[2]._mx;
+ my2 = _items2[info->index]->_subItems[info->subIndex]._walk[2]._my;
+ }
+
+ Common::Point point;
+
+ int y = info->pt2.y - info->pt1.y - my2 - my1;
+ int x = info->pt2.x - info->pt1.x - mx2 - mx1;
+ int a2;
+ int mgmLen;
+
+ _mgm.calcLength(&point, _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, x, y, &mgmLen, &a2, info->flags & 1);
+
+ int x1 = point.x;
+ int y1 = point.y;
+
+ if (!(info->flags & 1)) {
+ if (info->subIndex == 1 || info->subIndex == 0) {
+ a2 = -1;
+ x1 = mgmLen * _items2[info->index]->_subItems[info->subIndex]._walk[1]._mx;
+ x = x1;
+ info->pt2.x = x1 + info->pt1.x + mx1 + mx2;
+ }
+ }
+
+ if (!(info->flags & 1)) {
+ if (info->subIndex == 2 || info->subIndex == 3) {
+ a2 = -1;
+ y1 = mgmLen * _items2[info->index]->_subItems[info->subIndex]._walk[1]._my;
+ y = y1;
+ info->pt2.y = y1 + info->pt1.y + my1 + my2;
+ }
+ }
+
+ int cntX = 0;
+ int cntY = 0;
+
+ if (!(info->flags & 2)) {
+ cntX = _items2[info->index]->_subItems[info->subIndex]._walk[0]._mov->countPhasesWithFlag(-1, 1);
+ cntY = _items2[info->index]->_subItems[info->subIndex]._walk[0]._mov->countPhasesWithFlag(-1, 2);
+ }
+
+ if (mgmLen > 1) {
+ cntX += (mgmLen - 1) * _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov->countPhasesWithFlag(-1, 1);
+ cntY += (mgmLen - 1) * _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov->countPhasesWithFlag(-1, 2);
+ }
+
+ if (mgmLen > 0) {
+ cntX += _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov->countPhasesWithFlag(a2, 1);
+ cntY += _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov->countPhasesWithFlag(a2, 2);
+ }
+
+ if (!(info->flags & 4)) {
+ cntX += _items2[info->index]->_subItems[info->subIndex]._walk[2]._mov->countPhasesWithFlag(-1, 1);
+ cntY += _items2[info->index]->_subItems[info->subIndex]._walk[2]._mov->countPhasesWithFlag(-1, 2);
+ }
+
+ int dx1 = x - x1;
+ int dy1 = y - y1;
+
+ if (cntX)
+ x1 = (int)((double)dx1 / (double)cntX);
+ else
+ x1 = 0;
+
+ if (cntY)
+ y1 = (int)((double)dy1 / (double)cntY);
+ else
+ y1 = 0;
+
+ int v34 = dx1 - cntX * x1;
+ int v35 = dy1 - cntY * y1;
+ Common::Point x2;
+ Common::Point y2(v34, v35);
+
+ if (v34)
+ x2.x = v34 / abs(v34);
+ else
+ x2.x = 0;
+
+ if (v35)
+ x2.y = v35 / abs(v35);
+ else
+ x2.y = 0;
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+ ExCommand *ex;
+
+ if (info->flags & 2) {
+ ex = new ExCommand(
+ _items2[info->index]->_objectId,
+ 5,
+ _items2[info->index]->_subItems[info->subIndex]._walk[1]._movementId,
+ info->pt1.x,
+ info->pt1.y,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0);
+
+ ex->_field_14 = info->distance1;
+
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+ ex->_field_24 = 1;
+ ex->_excFlags |= 2;
+ } else {
+ ex = new ExCommand(
+ _items2[info->index]->_objectId,
+ 5,
+ _items2[info->index]->_subItems[info->subIndex]._walk[0]._movementId,
+ info->pt1.x,
+ info->pt1.y,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0);
+
+ ex->_field_14 = info->distance1;
+
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+ ex->_field_24 = 1;
+ ex->_excFlags |= 2;
+ mq->addExCommandToEnd(ex);
+
+ ex = _mgm.buildExCommand2(
+ _items2[info->index]->_subItems[info->subIndex]._walk[0]._mov,
+ _items2[info->index]->_objectId,
+ x1,
+ y1,
+ &x2,
+ &y2,
+ -1);
+ ex->_parId = mq->_id;
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+ }
+
+ mq->addExCommandToEnd(ex);
+
+ for (int i = 0; i < mgmLen; ++i) {
+ int par;
+
+ if (i == mgmLen - 1)
+ par = a2;
+ else
+ par = -1;
+
+ ex = _mgm.buildExCommand2(
+ _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov,
+ _items2[info->index]->_objectId,
+ x1,
+ y1,
+ &x2,
+ &y2,
+ par);
+ ex->_parId = mq->_id;
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+ mq->addExCommandToEnd(ex);
+ }
+
+ if (!(info->flags & 4)) {
+ ex = _mgm.buildExCommand2(
+ _items2[info->index]->_subItems[info->subIndex]._walk[2]._mov,
+ _items2[info->index]->_objectId,
+ x1,
+ y1,
+ &x2,
+ &y2,
+ -1);
+ ex->_parId = mq->_id;
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+
+ mq->addExCommandToEnd(ex);
+ }
+
+ ex = new ExCommand(_items2[info->index]->_objectId, 5, -1, info->pt2.x, info->pt2.y, 0, 1, 0, 0, 0);
+ ex->_field_14 = info->distance2;
+
+ ex->_keyCode = _items2[info->index]->_obj->_okeyCode;
+ ex->_field_24 = 0;
+ ex->_excFlags |= 2;
+
+ mq->addExCommandToEnd(ex);
+
+ return mq;
}
MovGraphLink *MovGraph2::findLink1(int x, int y, int idx, int fuzzyMatch) {
@@ -1272,7 +1693,7 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest,
} else if (linkInfoSource->link) {
linkInfoWorkSource.node = linkInfoSource->link->_movGraphNode1;
linkInfoWorkSource.link = 0;
-
+
Common::Array<MovGraphLink *> tmpList;
double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
@@ -1288,9 +1709,9 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest,
linkInfoWorkSource.link = 0;
linkInfoWorkSource.node = linkInfoSource->link->_movGraphNode2;
-
+
tmpList.clear();
-
+
newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
if (newDistance >= 0 && (minDistance < 0.0 || newDistance < minDistance)) {
@@ -1367,7 +1788,7 @@ void MGM::rebuildTables(int objId) {
_items[idx]->movements1.clear();
_items[idx]->movements2.clear();
- StaticANIObject *obj = g_fullpipe->_currentScene->getStaticANIObject1ById(objId, -1);
+ StaticANIObject *obj = g_fp->_currentScene->getStaticANIObject1ById(objId, -1);
if (!obj)
return;
@@ -1393,6 +1814,441 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) {
warning("STUB: MGM::genMovement()");
return 0;
+
+#if 0
+ if (!mgminfo->ani)
+ return 0;
+
+ mov = mgminfo->ani->_movement;
+
+ if (!mov && !mgminfo->ani->_statics)
+ return 0;
+
+ if (!(mgminfo->flags & 1)) {
+ if (mov)
+ mgminfo->staticsId1 = mov->_staticsObj2->_staticsId;
+ else
+ mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId;
+ }
+
+ if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) {
+ int nx = mgminfo->ani->_ox;
+ int ny = mgminfo->ani->_oy;
+
+ if (mgminfo->ani->_movement) {
+ mgminfo->ani->calcNextStep(&point2);
+ nx += point2.x;
+ ny += point2.y;
+ }
+
+ if (!(mgminfo->flags & 0x10))
+ mgminfo->x2 = nx;
+
+ if (!(mgminfo->flags & 0x20))
+ mgminfo->y2 = ny;
+ }
+
+ mov = mgminfo->ani->getMovementById(mgminfo->movementId);
+
+ if (!mov)
+ return 0;
+
+ itemIdx = getItemIndexById(mgminfo->ani->_id);
+ subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1);
+ st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId);
+ st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId);
+ subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2);
+
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, subIdx, st2idx, 0, 1);
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, st1idx, subOffset, 0, 1);
+
+ v71 = (Message *)(28 * itemIdx);
+ v16 = items[itemIdx].objId;
+ v17 = *(_DWORD *)(v16 + offsetof(MGMItem, staticsListCount));
+ off = *(_DWORD *)(v16 + offsetof(MGMItem, subItems));
+ v18 = (MGMSubItem *)(off + 24 * (subIdx + st2idx * v17));
+ x1 = (int)&v18->movement->go.CObject.vmt;
+ v19 = (MGMSubItem *)(off + 24 * (st1idx + subOffset * v17));
+ v69 = (LONG)&v19->movement->go.CObject.vmt;
+
+ if (subIdx != st2idx && !x1)
+ return 0;
+
+ if (st1idx != subOffset && !v69)
+ return 0;
+
+ int n1x = mgminfo->x1 - mgminfo->x2 - v18->x - v19->x;
+ int n1y = mgminfo->y1 - mgminfo->y2 - v18->y - v19->y;
+
+ mov->calcSomeXY(&point1, 0);
+
+ int n2x = point1.x;
+ int n2y = point1.y;
+ int mult;
+
+ if (mgminfo->flags & 0x40) {
+ mult = mgminfo->field_10;
+ len = -1;
+ n2x *= mult;
+ n2y *= mult;
+ } else {
+ calcLength(&point, mov, n1x, n1y, &mult, &len, 1);
+ n2x = point.x;
+ n2y = point.y;
+ }
+
+ if (!(mgminfo->flags & 2)) {
+ len = -1;
+ n2x = mult * point1.x;
+ n1x = mult * point1.x;
+ mgminfo->x1 = mgminfo->x2 + mult * point1.x + v18->x + v19->x;
+ }
+
+ if (!(mgminfo->flags & 4)) {
+ n2y = mult * point1.y;
+ n1y = mult * point1.y;
+ len = -1;
+ mgminfo->y1 = mgminfo->y2 + mult * point1.y + v18->y + v19->y;
+ }
+
+ int px = 0;
+ int py = 0;
+
+ if (x1) {
+ px = countPhases(itemIdx, subIdx, st2idx, 1);
+ py = countPhases(itemIdx, subIdx, st2idx, 2);
+ }
+
+ if (mult > 1) {
+ px += (mult - 1) * mov->countPhasesWithFlag(-1, 1);
+ py += (mult - 1) * mov->countPhasesWithFlag(-1, 2);
+ }
+
+ if (mult > 0) {
+ px += mov->countPhasesWithFlag(len, 1);
+ py += mov->countPhasesWithFlag(len, 2);
+ }
+
+ if (v69) {
+ px += countPhases(itemIdx, st1idx, subOffset, 1);
+ py += countPhases(itemIdx, st1idx, subOffset, 2);
+ }
+
+ int dx1 = n1x - n2x;
+ int dy1 = n1y - n2y;
+
+ if (px) {
+ x1 = (int)((double)dx1 / (double)px);
+ } else {
+ x1 = 0;
+ }
+
+ if (py) {
+ y1 = (int)((double)dy1 / (double)py);
+ } else {
+ y1 = 0;
+ }
+
+ y2.x = dx1 - px * x1;
+ y2.y = dy1 - py * y1;
+
+ if (n1x - n2x == px * x1)
+ x2.x = 0;
+ else
+ x2.x = (dx1 - px * x1) / abs(dx1 - px * x1);
+
+ if (dy1 == py * y1)
+ x2.y = 0;
+ else
+ x2.y = (dy1 - py * y1) / abs(dy1 - py * y1);
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+ ExCommand2 *ex2;
+
+ for (v42 = subIdx; v42 != st2idx; v42 = v43->staticsIndex) {
+ v43 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[v42 + st2idx * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
+ ex2 = buildExCommand2(v43->movement, mgminfo->ani->go._id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ for (i = 0; i < mult; ++i) {
+ int plen;
+
+ if (i == mult - 1)
+ plen = len;
+ else
+ plen = -1;
+
+ ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ for (j = st1idx; j != subOffset; j = v50->staticsIndex) {
+ v50 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[j + subOffset * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
+
+ ex2 = buildExCommand2(v50->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = mgminfo->field_1C;
+ ex->_keyCode = mgminfo->ani->_okeyCode;
+ ex->_field_24 = 0;
+ ex->_excFlags |= 3;
+
+ mq->addExCommandToEnd(ex);
+
+ return mq;
+#endif
+}
+
+void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) {
+ if (getItemIndexById(ani->_id) == -1)
+ return;
+
+ if (ani->_movement) {
+ ani->queueMessageQueue(0);
+ ani->_movement->gotoLastFrame();
+ ani->_statics = ani->_movement->_staticsObj2;
+
+ int x = ani->_movement->_ox;
+ int y = ani->_movement->_oy;
+
+ ani->_movement = 0;
+
+ ani->setOXY(x, y);
+ }
+
+ if (ani->_statics) {
+ Common::Point point;
+
+ getPoint(&point, ani->_id, ani->_statics->_staticsId, staticsId);
+
+ ani->setOXY(ani->_ox + point.x, ani->_oy + point.y);
+
+ ani->_statics = ani->getStaticsById(staticsId);
+ }
+}
+
+Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, int staticsId2) {
+ int idx = getItemIndexById(objectId);
+
+ if (idx == -1) {
+ point->x = -1;
+ point->y = -1;
+ } else {
+ int st1idx = getStaticsIndexById(idx, staticsId1);
+ int st2idx = getStaticsIndexById(idx, staticsId2);
+
+ if (st1idx == st2idx) {
+ point->x = 0;
+ point->y = 0;
+ } else {
+ int subidx = st1idx + st2idx * _items[idx]->statics.size();
+
+ if (!_items[idx]->subItems[subidx]->movement) {
+ clearMovements2(idx);
+ recalcOffsets(idx, st1idx, st2idx, false, true);
+
+ if (!_items[idx]->subItems[subidx]->movement) {
+ clearMovements2(idx);
+ recalcOffsets(idx, st1idx, st2idx, true, false);
+ }
+ }
+
+ MGMSubItem *sub = _items[idx]->subItems[subidx];
+
+ if (sub->movement) {
+ point->x = sub->x;
+ point->y = sub->y;
+ } else {
+ point->x = 0;
+ point->y = 0;
+ }
+ }
+ }
+
+ return point;
+}
+
+int MGM::getStaticsIndexById(int idx, int16 id) {
+ if (!_items[idx]->statics.size())
+ return -1;
+
+ for (uint i = 0; i < _items[idx]->statics.size(); i++) {
+ if (_items[idx]->statics[i]->_staticsId == id)
+ return i;
+ }
+
+ return 0;
+}
+
+int MGM::getStaticsIndex(int idx, Statics *st) {
+ if (!_items[idx]->statics.size())
+ return -1;
+
+ for (uint i = 0; i < _items[idx]->statics.size(); i++) {
+ if (_items[idx]->statics[i] == st)
+ return i;
+ }
+
+ return 0;
+}
+
+void MGM::clearMovements2(int idx) {
+ _items[idx]->movements2.clear();
+}
+
+int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) {
+ warning("STUB: MGM::recalcOffsets()");
+
+ return 0;
+}
+
+Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) {
+ Common::Point point;
+
+ mov->calcSomeXY(point, 0);
+ int p1x = point.x;
+ int p1y = point.y;
+
+ int newmult = 0;
+ int oldlen = *len;
+
+ if (abs(p1y) > abs(p1x)) {
+ if (mov->calcSomeXY(point, 0)->y)
+ newmult = (int)((double)y / point.y);
+ } else if (mov->calcSomeXY(point, 0)->x) {
+ newmult = (int)((double)x / point.y);
+ }
+
+ if (newmult < 0)
+ newmult = 0;
+
+ *mult = newmult;
+
+ int phase = 1;
+ int sz;
+
+ if (flag) {
+ if (abs(p1y) > abs(p1x)) {
+ while (abs(p1y * newmult + mov->calcSomeXY(point, 0)->y) < abs(y)) {
+ sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ if (phase >= sz) {
+ phase--;
+
+ break;
+ }
+
+ phase++;
+ }
+ } else {
+ while (abs(p1x * newmult + mov->calcSomeXY(point, 0)->x) < abs(x)) {
+ sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
+
+ if (phase >= sz) {
+ phase--;
+
+ break;
+ }
+
+ phase++;
+ }
+ }
+
+ *len = phase - 1;
+ } else {
+ *len = -1;
+ }
+
+ int p2x = 0;
+ int p2y = 0;
+
+ if (!oldlen)
+ oldlen = -1;
+
+ if (oldlen > 0) {
+ ++*mult;
+
+ mov->calcSomeXY(point, 0);
+ p2x = point.x;
+ p2y = point.y;
+
+ if (abs(p1y) > abs(p1x))
+ p2x = p1x;
+ else
+ p2y = p1y;
+ }
+
+ pRes->x = p2x + p1x * newmult;
+ pRes->y = p2y + p1y * newmult;
+
+ return pRes;
+}
+
+ExCommand2 *MGM::buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len) {
+ uint cnt;
+
+ if (mov->_currMovement)
+ cnt = mov->_currMovement->_dynamicPhases.size();
+ else
+ cnt = mov->_dynamicPhases.size();
+
+ if (len > 0 && cnt > (uint)len)
+ cnt = len;
+
+ Common::Point **points = (Common::Point **)malloc(sizeof(Common::Point *) * cnt);
+
+ for (uint i = 0; i < cnt; i++) {
+ int flags = mov->getDynamicPhaseByIndex(i)->getDynFlags();
+
+ points[i] = new Common::Point;
+
+ if (flags & 1) {
+ points[i]->x = x1 + x2->x;
+
+ y2->x -= x2->x;
+
+ if (!y2->x)
+ x2->x = 0;
+ }
+
+ if (flags & 2) {
+ points[i]->y = y1 + x2->y;
+
+ y2->y -= x2->y;
+
+ if (!y2->y)
+ x2->y = 0;
+ }
+ }
+
+ ExCommand2 *ex = new ExCommand2(20, objId, points, cnt);
+ ex->_excFlags = 2;
+ ex->_messageNum = mov->_id;
+ ex->_field_14 = len;
+ ex->_field_24 = 1;
+ ex->_keyCode = -1;
+
+ for (uint i = 0; i < cnt; i++)
+ delete points[i];
+
+ free(points);
+
+ return ex;
}
MovGraphLink::MovGraphLink() {
@@ -1409,6 +2265,11 @@ MovGraphLink::MovGraphLink() {
_objtype = kObjTypeMovGraphLink;
}
+MovGraphLink::~MovGraphLink() {
+ warning("STUB: MovGraphLink::~MovGraphLink()");
+}
+
+
bool MovGraphLink::load(MfcArchive &file) {
debug(5, "MovGraphLink::load()");
@@ -1484,7 +2345,7 @@ void ReactParallel::createRegion() {
for (int i = 0; i < 4; i++)
_points[i] = new Common::Point;
- double at = atan2((double)(_x1 - _x2), (double)(_y1 - _y2)) + 1.570796;
+ double at = atan2((double)(_x1 - _x2), (double)(_y1 - _y2)) + 1.570796; // pi/2
double sn = sin(at);
double cs = cos(at);
@@ -1504,20 +2365,28 @@ void ReactParallel::createRegion() {
// GdiObject::Attach(_rgn, CreatePolygonRgn(_points, 4, 2);
}
-void ReactParallel::method14() {
- warning("STUB: ReactParallel::method14()");
+void ReactParallel::setCenter(int x1, int y1, int x2, int y2) {
+ _x1 = x1;
+ _y1 = y1;
+ _x2 = x2;
+ _y2 = y2;
}
ReactPolygonal::ReactPolygonal() {
- _field_C = 0;
- _field_10 = 0;
+ _centerX = 0;
+ _centerY = 0;
+ _bbox = 0;
+}
+
+ReactPolygonal::~ReactPolygonal() {
+ delete _bbox;
}
bool ReactPolygonal::load(MfcArchive &file) {
debug(5, "ReactPolygonal::load()");
- _field_C = file.readUint32LE();
- _field_10 = file.readUint32LE();
+ _centerX = file.readUint32LE();
+ _centerY = file.readUint32LE();
_pointCount = file.readUint32LE();
if (_pointCount > 0) {
@@ -1544,10 +2413,54 @@ void ReactPolygonal::createRegion() {
}
}
-void ReactPolygonal::method14() {
- warning("STUB: ReactPolygonal::method14()");
+void ReactPolygonal::setCenter(int x1, int y1, int x2, int y2) {
+ int cX = (x2 + x1) / 2;
+ int cY = (y2 + y1) / 2;
+
+ if (_points) {
+ for (int i = 0; i < _pointCount; i++) {
+ _points[i]->x += cX - _centerX;
+ _points[i]->y += cY - _centerY;
+ }
+ }
+
+ _centerX = cX;
+ _centerY = cY;
}
+void ReactPolygonal::getBBox(Common::Rect *rect) {
+ if (!_pointCount)
+ return;
+
+ if (_bbox) {
+ *rect = *_bbox;
+ return;
+ }
+
+ rect->left = _points[0]->x;
+ rect->top = _points[0]->y;
+ rect->right = _points[0]->x;
+ rect->bottom = _points[0]->y;
+
+ for (int i = 1; i < _pointCount; i++) {
+ if (rect->left > _points[i]->x)
+ rect->left = _points[i]->x;
+
+ if (rect->top < _points[i]->y)
+ rect->top = _points[i]->y;
+
+ if (rect->right < _points[i]->x)
+ rect->right = _points[i]->x;
+
+ if (rect->bottom > _points[i]->y)
+ rect->bottom = _points[i]->y;
+ }
+
+ _bbox = new Common::Rect;
+ *_bbox = *rect;
+}
+
+
bool MovGraphReact::pointInRegion(int x, int y) {
if (_pointCount < 3) {
return false;
@@ -1557,15 +2470,15 @@ bool MovGraphReact::pointInRegion(int x, int y) {
double xinters;
Common::Point p, p1, p2;
- p.x = (double)x;
- p.y = (double)y;
+ p.x = x;
+ p.y = y;
- p1.x = (double)_points[0]->x;
- p1.y = (double)_points[0]->y;
+ p1.x = _points[0]->x;
+ p1.y = _points[0]->y;
for (int i = 1; i <= _pointCount; i++) {
- p2.x = (double)_points[i % _pointCount]->x;
- p2.y = (double)_points[i % _pointCount]->y;
+ p2.x = _points[i % _pointCount]->x;
+ p2.y = _points[i % _pointCount]->y;
if (p.y > MIN(p1.y, p2.y)) {
if (p.y <= MAX(p1.y, p2.y)) {
@@ -1590,16 +2503,20 @@ bool MovGraphReact::pointInRegion(int x, int y) {
}
int startWalkTo(int objId, int objKey, int x, int y, int a5) {
- MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId);
+ MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId);
if (mc)
- return (mc->method34(g_fullpipe->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0);
+ return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0);
return 0;
}
int doSomeAnimation(int objId, int objKey, int a3) {
- warning("STUB: doSomeAnimation(%d, %d, %d)", objId, objKey, a3);
+ StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(objId, objKey);
+ MctlCompound *cmp = getCurrSceneSc2MotionController();
+
+ if (ani && cmp)
+ return cmp->method3C(ani, a3);
return 0;
}