diff options
author | Eugene Sandulenko | 2013-09-08 23:53:02 +0300 |
---|---|---|
committer | Eugene Sandulenko | 2013-09-08 23:56:04 +0300 |
commit | 747e70a38ebd08450714fdb01dd45139ac9504a1 (patch) | |
tree | 61513c7f6b7272ba837f55194adf059bc114d735 | |
parent | 940c686858d9a0bf92c1473b9a81653a9937b88a (diff) | |
download | scummvm-rg350-747e70a38ebd08450714fdb01dd45139ac9504a1.tar.gz scummvm-rg350-747e70a38ebd08450714fdb01dd45139ac9504a1.tar.bz2 scummvm-rg350-747e70a38ebd08450714fdb01dd45139ac9504a1.zip |
FULLPIPE: Implement CInteractionController::handleInteraction()
-rw-r--r-- | engines/fullpipe/gfx.cpp | 89 | ||||
-rw-r--r-- | engines/fullpipe/gfx.h | 2 | ||||
-rw-r--r-- | engines/fullpipe/interaction.cpp | 309 | ||||
-rw-r--r-- | engines/fullpipe/interaction.h | 6 | ||||
-rw-r--r-- | engines/fullpipe/messages.cpp | 32 | ||||
-rw-r--r-- | engines/fullpipe/messages.h | 3 | ||||
-rw-r--r-- | engines/fullpipe/motion.cpp | 14 | ||||
-rw-r--r-- | engines/fullpipe/motion.h | 3 | ||||
-rw-r--r-- | engines/fullpipe/statics.cpp | 55 | ||||
-rw-r--r-- | engines/fullpipe/statics.h | 4 |
10 files changed, 466 insertions, 51 deletions
diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index c46bdfab55..c6024d15e0 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -365,6 +365,95 @@ bool GameObject::canInteractAny(GameObject *obj2, int invId) { return false; } +bool GameObject::getPicAniInfo(PicAniInfo *info) { + if (_objtype == kObjTypePictureObject) { + info->type = 2; + info->objectId = _id; + info->sceneId = 0; + info->field_8 = _okeyCode; + info->flags = _flags; + info->field_24 = _field_8; + info->ox = _ox; + info->oy = _oy; + info->priority = _priority; + + return true; + } + + if (_objtype == kObjTypeStaticANIObject) { + StaticANIObject *ani = (StaticANIObject *)this; + + info->type = (ani->_messageQueueId << 16) | 1; + info->objectId = ani->_id; + info->field_8 = ani->_okeyCode; + info->sceneId = ani->_sceneId; + info->flags = ani->_flags; + info->field_24 = ani->_field_8; + if (ani->_movement) { + info->ox = ani->_movement->_ox; + info->oy = ani->_movement->_oy; + } else { + info->ox = ani->_ox; + info->oy = ani->_oy; + } + info->priority = ani->_priority; + + if (ani->_statics) + info->staticsId = ani->_statics->_staticsId; + + if (ani->_movement) { + info->movementId = ani->_movement->_id; + info->dynamicPhaseIndex = ani->_movement->_currDynamicPhaseIndex; + } + + info->someDynamicPhaseIndex = ani->_someDynamicPhaseIndex; + + return true; + } + + return false; +} + +bool GameObject::setPicAniInfo(PicAniInfo *picAniInfo) { + if (!(picAniInfo->type & 3)) { + warning("StaticANIObject::setPicAniInfo(): Wrong type: %d", picAniInfo->type); + + return false; + } + + if (picAniInfo->type & 3) { + setOXY(picAniInfo->ox, picAniInfo->oy); + _priority = picAniInfo->priority; + _okeyCode = picAniInfo->field_8; + setFlags(picAniInfo->flags); + _field_8 = picAniInfo->field_24; + } + + if (picAniInfo->type & 1) { + StaticANIObject *ani = (StaticANIObject *)this; + + ani->_messageQueueId = (picAniInfo->type >> 16) & 0xffff; + + if (picAniInfo->staticsId) { + ani->_statics = ani->getStaticsById(picAniInfo->staticsId); + } else { + ani->_statics = 0; + } + + if (picAniInfo->movementId) { + ani->_movement = ani->getMovementById(picAniInfo->movementId); + if (ani->_movement) + ani->_movement->setDynamicPhaseIndex(picAniInfo->dynamicPhaseIndex); + } else { + ani->_movement = 0; + } + + ani->setSomeDynamicPhaseIndex(picAniInfo->someDynamicPhaseIndex); + } + + return true; +} + Picture::Picture() { _x = 0; _y = 0; diff --git a/engines/fullpipe/gfx.h b/engines/fullpipe/gfx.h index d09a589704..10b82efede 100644 --- a/engines/fullpipe/gfx.h +++ b/engines/fullpipe/gfx.h @@ -143,6 +143,8 @@ class GameObject : public CObject { const char *getName() { return _objectName; } bool canInteractAny(GameObject *obj2, int invId); + bool getPicAniInfo(PicAniInfo *info); + bool setPicAniInfo(PicAniInfo *info); }; class PictureObject : public GameObject { diff --git a/engines/fullpipe/interaction.cpp b/engines/fullpipe/interaction.cpp index f9ea41b2ae..4153724b63 100644 --- a/engines/fullpipe/interaction.cpp +++ b/engines/fullpipe/interaction.cpp @@ -25,10 +25,11 @@ #include "fullpipe/interaction.h" #include "fullpipe/gameloader.h" #include "fullpipe/statics.h" +#include "fullpipe/motion.h" namespace Fullpipe { -int handleObjectInteraction(GameObject *subject, GameObject *object, int invId) { +int handleObjectInteraction(StaticANIObject *subject, GameObject *object, int invId) { return getGameLoaderInteractionController()->handleInteraction(subject, object, invId); } @@ -72,7 +73,303 @@ void CInteractionController::sortInteractions(int sceneId) { Common::sort(_interactions.begin(), _interactions.end(), CInteractionController::compareInteractions); } -bool CInteractionController::handleInteraction(GameObject *subj, GameObject *obj, int invId) { +bool CInteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) { + if (subj) { + if (!subj->isIdle() || (subj->_flags & 0x100)) + return false; + } + + if (!_interactions.size()) + return false; + + CInteraction *inter = 0; + CInteraction *previnter = 0; + int dur = 0; + int mindur = 0xFFFF; + + MessageQueue *mq; + ExCommand *ex; + + for (CObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) { + CInteraction *cinter = (CInteraction *)*i; + + if (!cinter->canInteract(subj, obj, invId)) + continue; + + if ((inter || cinter->_objectId2) && (!obj || cinter->_objectId3 != obj->_id)) { + if (cinter->_messageQueue) + cinter->_messageQueue->calcDuration(subj); + + PicAniInfo aniInfo; + + obj->getPicAniInfo(&aniInfo); + + if (cinter->_staticsId1) { + StaticANIObject *ani = (StaticANIObject *)obj; + ani->_messageQueueId = 0; + ani->changeStatics2(cinter->_staticsId1); + } + int xpos = cinter->_xOffs + obj->_ox; + int ypos = cinter->_yOffs + obj->_oy; + + obj->setPicAniInfo(&aniInfo); + + if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1) { + mq = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->method4C(subj, xpos, ypos, 1, cinter->_staticsId2); + if (mq) { + dur = mq->calcDuration(subj); + delete mq; + } else { + dur = 0x10000; + } + inter = previnter; + } else { + dur = 0; + } + if (dur < mindur) { + inter = cinter; + mindur = dur; + previnter = cinter; + } + } else { + inter = cinter; + break; + } + } + + if (!inter) + return false; + + if (!inter->_objectId2) { + StaticANIObject *ani = (StaticANIObject *)obj; + + if (!ani->isIdle()) + return false; + + if (ani->_flags & 0x100) + return false; + + if (!inter->_staticsId1 || !(inter->_flags & 1)) + goto LABEL_38; + + if (ani->_movement || ani->_statics == 0 || ani->_statics->_staticsId != inter->_staticsId1) { + mq = ani->changeStatics1(inter->_staticsId1); + if (!mq) + return false; + + ex = new ExCommand((subj ? subj->_id : 0), 55, 0, 0, 0, 0, 1, 0, 0, 0); + ex->_x = obj->_id; + ex->_y = obj->_okeyCode; + ex->_keyCode = subj ? subj->_okeyCode : 0; + ex->_excFlags = 3; + ex->_field_14 = (obj->_objtype != kObjTypePictureObject); + ex->_field_20 = invId; + mq->_exCommands.push_back(ex); + + if (mq->_isFinished) { + mq->_isFinished = 0; + ani->queueMessageQueue(mq); + } + } else { + if (ani->getMessageQueue()) + ani->queueMessageQueue(0); +LABEL_38: + if (inter->_messageQueue) { + mq = new MessageQueue(inter->_messageQueue, 0, 1); + mq->changeParam28ForObjectId(ani->_id, -1, ani->_okeyCode); + + if (!mq->chain(0)) + return false; + } + } + return true; + } + + if (obj && !subj) + return true; + + if (!obj || inter->_objectId3 == obj->_id) { + if (subj) { + if (inter->_messageQueue) { + if (subj->isIdle()) { + mq = new MessageQueue(inter->_messageQueue, 0, 1); + + if (!mq->chain(subj)) { + if (mq) + delete mq; + + return false; + } + } + } + } + return true; + } + + if (inter->isOverlapping(subj, obj)) { + if (obj->_objtype == kObjTypeStaticANIObject) { + StaticANIObject *ani = (StaticANIObject *)obj; + + ani->queueMessageQueue(0); + + if (inter->_staticsId1) + ani->changeStatics2(inter->_staticsId1); + + if (!(inter->_flags & 0x10000)) + obj->_flags |= 0x80; + } + + if (!inter->_messageQueue) + return false; + + subj->setOXY(inter->_xOffs + obj->_ox, inter->_yOffs + obj->_oy); + + mq = new MessageQueue(inter->_messageQueue, 0, 1); + mq->changeParam28ForObjectId(obj->_id, -1, obj->_okeyCode); + mq->_flags |= 1; + + if (!(inter->_flags & 0x10000)) { + ex = new ExCommand(obj->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = obj->_okeyCode; + ex->_field_14 = 0x100; + ex->_messageNum = 0; + ex->_excFlags = 3; + mq->_exCommands.push_back(ex); + } + + ex = new ExCommand(obj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = obj->_okeyCode; + ex->_field_14 = 0x100; + ex->_messageNum = 0; + ex->_excFlags = 3; + mq->_exCommands.push_back(ex); + + ex = new ExCommand(subj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = subj->_okeyCode; + ex->_field_14 = 0x100; + ex->_messageNum = 0; + ex->_excFlags = 3; + mq->_exCommands.push_back(ex); + + ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0); + ex->_excFlags |= 3; + ex->_keyCode = 0; + mq->_exCommands.push_back(ex); + + if (!mq->chain(subj)) { + delete mq; + + return false; + } + + subj->_flags |= 1; + obj->_flags |= 1; + } else { + bool someFlag = false; + PicAniInfo aniInfo; + + obj->getPicAniInfo(&aniInfo); + + if (obj->_objtype == kObjTypeStaticANIObject && inter->_staticsId1) { + StaticANIObject *ani = (StaticANIObject *)obj; + + ani->_messageQueueId = 0; + ani->changeStatics2(inter->_staticsId1); + } + + int xpos = inter->_yOffs + obj->_ox; + int ypos = inter->_yOffs + obj->_oy; + + obj->setPicAniInfo(&aniInfo); + + if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1 + || (inter->_staticsId2 != 0 && (subj->_statics == 0 || subj->_statics->_staticsId != inter->_staticsId2))) { + mq = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->method34(subj, xpos, ypos, 1, inter->_staticsId2); + + if (!mq) + return false; + + ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0); + ex->_x = obj->_id; + ex->_y = obj->_okeyCode; + ex->_keyCode = subj->_okeyCode; + ex->_excFlags = 3; + ex->_field_20 = invId; + ex->_field_14 = (obj->_objtype != kObjTypePictureObject); + mq->_exCommands.push_back(ex); + + someFlag = true; + + ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0); + ex->_x = xpos; + ex->_y = ypos; + ex->_excFlags |= 3; + ex->_keyCode = 6; + ex->_field_14 = obj->_id; + ex->_field_20 = obj->_okeyCode; + ex->postMessage(); + } + + if (!inter->_staticsId1 || !(inter->_flags & 1)) + return true; + + StaticANIObject *ani = (StaticANIObject *)obj; + + if (!ani->isIdle()) + return false; + + if (ani->getMessageQueue()) + ani->queueMessageQueue(0); + + if (!ani->_statics || ani->_statics->_staticsId != inter->_staticsId1 || ani->_movement) { + mq = ani->changeStatics1(inter->_staticsId1); + + if (!mq) + return false; + + if (someFlag) { + if (!(inter->_flags & 0x10000)) { + if (mq->_isFinished) { + ani->_flags |= 0x80u; + } else { + ex = new ExCommand(ani->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0); + ex->_field_14 = 0x80; + ex->_keyCode = ani->_okeyCode; + ex->_excFlags = 3; + mq->_exCommands.push_back(ex); + } + } + ex = new ExCommand(ani->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_field_14 = 0x100; + ex->_excFlags = 3; + mq->_exCommands.push_back(ex); + } else { + ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0); + ex->_x = ani->_id; + ex->_y = ani->_okeyCode; + ex->_keyCode = subj->_okeyCode; + ex->_excFlags = 2; + ex->_field_14 = (obj->_objtype != kObjTypePictureObject); + ex->_field_20 = invId; + mq->_exCommands.push_back(ex); + + if (!mq->_isFinished) + return true; + + mq->_isFinished = 0; + ani->queueMessageQueue(mq); + } + } else { + obj->_flags |= 1; + + if (inter->_flags & 0x10000) + return true; + + obj->_flags |= 0x80; + } + } + return true; } @@ -170,11 +467,13 @@ bool CInteraction::canInteract(GameObject *obj1, GameObject *obj2, int invId) { return true; } -bool CInteraction::isOverlapping(StaticANIObject *subj, StaticANIObject *obj) { +bool CInteraction::isOverlapping(StaticANIObject *subj, GameObject *obj) { + StaticANIObject *ani = (StaticANIObject *)obj; + if (abs(_xOffs + obj->_ox - subj->_ox) <= 1 && abs(obj->_oy + _yOffs - subj->_oy) <= 1) { - if (!this->_staticsId2 || subj->_statics != 0 && subj->_statics->_staticsId == _staticsId2) { - if (!_staticsId1 || !(_flags & 1) || obj->_statics != 0 && obj->_statics->_staticsId == _staticsId1) + if (!_staticsId2 || subj->_statics != 0 && subj->_statics->_staticsId == _staticsId2) { + if (!_staticsId1 || !(_flags & 1) || ani->_statics != 0 && ani->_statics->_staticsId == _staticsId1) return true; } } diff --git a/engines/fullpipe/interaction.h b/engines/fullpipe/interaction.h index d5ea5eaf9c..e3090334fe 100644 --- a/engines/fullpipe/interaction.h +++ b/engines/fullpipe/interaction.h @@ -31,7 +31,7 @@ class GameObject; class MessageQueue; class StaticANIObject; -int handleObjectInteraction(GameObject *subject, GameObject *object, int invId); +int handleObjectInteraction(StaticANIObject *subject, GameObject *object, int invId); class CInteraction : public CObject { public: @@ -54,7 +54,7 @@ class CInteraction : public CObject { CInteraction(); virtual bool load(MfcArchive &file); bool canInteract(GameObject *obj1, GameObject *obj2, int invId); - bool isOverlapping(StaticANIObject *subj, StaticANIObject *obj); + bool isOverlapping(StaticANIObject *subj, GameObject *obj); }; class CInteractionController : public CObject { @@ -76,7 +76,7 @@ class CInteractionController : public CObject { void sortInteractions(int sceneId); - bool handleInteraction(GameObject *subj, GameObject *obj, int invId); + bool handleInteraction(StaticANIObject *subj, GameObject *obj, int invId); }; struct EntranceInfo { diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index e4dfcf558f..acf44f5729 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -445,6 +445,38 @@ void MessageQueue::replaceKeyCode(int key1, int key2) { } } +int MessageQueue::calcDuration(StaticANIObject *obj) { + int res; + ExCommand *ex; + Movement *mov; + + for (uint i = 0; (ex = getExCommandByIndex(i)); i++) + if (ex->_parentId == obj->_id) { + if (ex->_messageKind == 1 || ex->_messageKind == 20) { + if ((mov = obj->getMovementById(ex->_messageNum)) != 0) { + if (ex->_field_14 >= 1) + res += ex->_field_14; + else + res += mov->calcDuration(); + } + } + } + + return res; +} + +void MessageQueue::changeParam28ForObjectId(int objId, int oldParam28, int newParam28) { + for (uint i = 0; i < _exCommands.size(); i++) { + ExCommand *ex = getExCommandByIndex(i); + int k = ex->_messageKind; + + if ((k == 1 || k == 20 || k == 5 || k == 6 || k == 2 || k == 18 || k == 19 || k == 22 || k == 55) + && ex->_keyCode == oldParam28 + && ex->_parentId == objId) + ex->_keyCode = newParam28; + } +} + MessageQueue *GlobalMessageQueueList::getMessageQueueById(int id) { for (Common::Array<MessageQueue *>::iterator s = begin(); s != end(); ++s) { if ((*s)->_id == id) diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h index 676432574b..960e184a88 100644 --- a/engines/fullpipe/messages.h +++ b/engines/fullpipe/messages.h @@ -133,6 +133,9 @@ class MessageQueue : public CObject { bool checkGlobalExCommandList1(); bool checkGlobalExCommandList2(); + + int calcDuration(StaticANIObject *obj); + void changeParam28ForObjectId(int objId, int oldParam28, int newParam28); }; class GlobalMessageQueueList : public Common::Array<MessageQueue *> { diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 6d07747c9f..4ba03f123f 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -76,10 +76,22 @@ void CMctlCompound::addObject(StaticANIObject *obj) { warning("STUB: CMctlCompound::addObject()"); } - void CMctlCompound::initMovGraph2() { +void CMctlCompound::initMovGraph2() { warning("STUB: CMctlCompound::initMovGraph2()"); } +MessageQueue *CMctlCompound::method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) { + warning("STUB: CMctlCompound::method34()"); + + return 0; +} + +MessageQueue *CMctlCompound::method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) { + warning("STUB: CMctlCompound::method4C()"); + + return 0; +} + bool CMctlCompoundArray::load(MfcArchive &file) { debug(5, "CMctlCompoundArray::load()"); diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index 318a6b383f..f110ac30df 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -62,6 +62,9 @@ class CMctlCompound : public CMotionController { virtual void addObject(StaticANIObject *obj); void initMovGraph2(); + + MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId); + MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId); }; class Unk2 : public CObject { diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 7f083101f9..1fd02f8eb6 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -815,46 +815,6 @@ void StaticANIObject::adjustSomeXY() { warning("STUB: StaticANIObject::adjustSomeXY()"); } -bool StaticANIObject::setPicAniInfo(PicAniInfo *picAniInfo) { - if (!(picAniInfo->type & 3)) { - warning("StaticANIObject::setPicAniInfo(): Wrong type: %d", picAniInfo->type); - - return false; - } - - debug(0, "StaticANIObject::setPicAniInfo() (%s [%d]) type: %d, statid: %d, movid: %d", transCyrillic((byte *)_objectName), _id, picAniInfo->type, picAniInfo->staticsId, picAniInfo->movementId); - - if (picAniInfo->type & 3) { - setOXY(picAniInfo->ox, picAniInfo->oy); - _priority = picAniInfo->priority; - _okeyCode = picAniInfo->field_8; - setFlags(picAniInfo->flags); - _field_8 = picAniInfo->field_24; - } - - if (picAniInfo->type & 1) { - _messageQueueId = (picAniInfo->type >> 16) & 0xffff; - - if (picAniInfo->staticsId) { - _statics = getStaticsById(picAniInfo->staticsId); - } else { - _statics = 0; - } - - if (picAniInfo->movementId) { - _movement = getMovementById(picAniInfo->movementId); - if (_movement) - _movement->setDynamicPhaseIndex(picAniInfo->dynamicPhaseIndex); - } else { - _movement = 0; - } - - setSomeDynamicPhaseIndex(picAniInfo->someDynamicPhaseIndex); - } - - return true; -} - MessageQueue *StaticANIObject::changeStatics1(int msgNum) { warning("STUB: StaticANIObject::changeStatics1(%d)", msgNum); @@ -1358,6 +1318,21 @@ void Movement::updateCurrDynamicPhase() { } } +int Movement::calcDuration() { + int res = 0; + + if (_currMovement) + for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) { + res += ((DynamicPhase *)_currMovement->_dynamicPhases[i])->_initialCountdown; + } + else + for (uint i = 0; i < _dynamicPhases.size(); i++) { + res += ((DynamicPhase *)_dynamicPhases[i])->_initialCountdown; + } + + return res; +} + void Movement::setDynamicPhaseIndex(int index) { debug(7, "Movement::setDynamicPhaseIndex(%d)", index); while (_currDynamicPhaseIndex < index) diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h index 295da9b676..3d45ac6623 100644 --- a/engines/fullpipe/statics.h +++ b/engines/fullpipe/statics.h @@ -145,6 +145,8 @@ class Movement : public GameObject { void setDynamicPhaseIndex(int index); DynamicPhase *getDynamicPhaseByIndex(int idx); + int calcDuration(); + void removeFirstPhase(); bool gotoNextFrame(int callback1, void (*callback2)(int *)); bool gotoPrevFrame(); @@ -207,8 +209,6 @@ class StaticANIObject : public GameObject { void initMovements(); void loadMovementsPixelData(); - bool setPicAniInfo(PicAniInfo *picAniInfo); - void setSomeDynamicPhaseIndex(int val) { _someDynamicPhaseIndex = val; } void adjustSomeXY(); |