bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) { if (subj) { if (!subj->isIdle() || (subj->_flags & 0x100)) return false; } if (!_interactions.size()) return false; Interaction *inter = 0; Interaction *previnter = 0; int dur = 0; int mindur = 0xFFFF; MessageQueue *mq; ExCommand *ex; for (InteractionList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) { Interaction *cinter = *i; if (!cinter->canInteract(subj, obj, invId)) continue; if ((inter || cinter->_objectId2) && (!obj || cinter->_objectId3 != obj->_id)) { if (cinter->_messageQueue) cinter->_messageQueue->calcDuration(subj); debugC(5, kDebugInteractions, "Interaction: %s", transCyrillic(cinter->_actionName)); PicAniInfo aniInfo; obj->getPicAniInfo(aniInfo); if (cinter->_staticsId1 && obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<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) { debugC(0, kDebugPathfinding, "Calling makeQueue() at [%d, %d]", xpos, ypos); mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->makeQueue(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) { if (obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); if (inter->_flags & 1) { if (!ani->isIdle()) return false; if (ani->_flags & 0x100) return false; } else if (inter->_staticsId1 != 0) { 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->_odelay; ex->_param = subj ? subj->_odelay : 0; ex->_excFlags = 3; ex->_z = (obj->_objtype != kObjTypePictureObject); ex->_field_20 = invId; mq->addExCommandToEnd(ex); if (mq->_isFinished) { mq->_isFinished = 0; ani->queueMessageQueue(mq); } return true; } else { if (ani->getMessageQueue()) ani->queueMessageQueue(0); } } } if (inter->_messageQueue) { mq = new MessageQueue(inter->_messageQueue, 0, 1); mq->changeParam28ForObjectId(obj->_id, -1, obj->_odelay); 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)) { delete mq; return false; } } } } return true; } if (inter->isOverlapping(subj, obj)) { if (obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<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->_odelay); mq->_flags |= 1; if (!(inter->_flags & 0x10000)) { ex = new ExCommand(obj->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0); ex->_param = obj->_odelay; ex->_z = 0x80; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } ex = new ExCommand(obj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = obj->_odelay; ex->_z = 0x100; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); ex = new ExCommand(subj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = subj->_odelay; ex->_z = 0x100; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 3; ex->_param = 0; mq->addExCommandToEnd(ex); if (!mq->chain(subj)) { delete mq; return false; } subj->_flags |= 0x100; obj->_flags |= 0x100; } else { bool someFlag = false; PicAniInfo aniInfo; obj->getPicAniInfo(aniInfo); if (obj->_objtype == kObjTypeStaticANIObject && inter->_staticsId1) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); ani->_messageQueueId = 0; ani->changeStatics2(inter->_staticsId1); } int xpos = inter->_xOffs + 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_fp->_currentScene->_sceneId)->startMove(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->_odelay; ex->_param = subj->_odelay; ex->_excFlags = 3; ex->_field_20 = invId; ex->_z = (obj->_objtype != kObjTypePictureObject); mq->addExCommandToEnd(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->_param = 6; ex->_z = obj->_id; ex->_field_20 = obj->_odelay; ex->postMessage(); } if (!inter->_staticsId1 || !(inter->_flags & 1)) return true; if (obj->_objtype != kObjTypeStaticANIObject) return false; StaticANIObject *ani = static_cast<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->_z = 0x80; ex->_param = ani->_odelay; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } } ex = new ExCommand(ani->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = ani->_odelay; ex->_z = 0x100; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } else { ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0); ex->_x = ani->_id; ex->_y = ani->_odelay; ex->_param = subj->_odelay; ex->_excFlags = 2; ex->_z = (obj->_objtype != kObjTypePictureObject); ex->_field_20 = invId; mq->addExCommandToEnd(ex); if (!mq->_isFinished) return true; mq->_isFinished = 0; ani->queueMessageQueue(mq); } } else { obj->_flags |= 0x100; if (inter->_flags & 0x10000) return true; obj->_flags |= 0x80; } } return true; }
bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) { if (subj) { if (!subj->isIdle() || (subj->_flags & 0x100)) return false; } if (!_interactions.size()) return false; Interaction *inter = 0; Interaction *previnter = 0; int dur = 0; int mindur = 0xFFFF; MessageQueue *mq; ExCommand *ex; for (ObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) { Interaction *cinter = (Interaction *)*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)->doWalkTo(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)) { 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; }
int global_messageHandler4(ExCommand *cmd) { StaticANIObject *ani = 0; switch (cmd->_messageKind) { case 18: { MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(cmd->_messageNum), cmd->_parId, 0); if (cmd->_excFlags & 1) mq->_flag1 = 1; else mq->_flag1 = 0; mq->sendNextCommand(); break; } case 2: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->trySetMessageQueue(cmd->_messageNum, cmd->_parId); break; case 1: { if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; int flags = cmd->_field_14; if (flags <= 0) flags = -1; if (cmd->_excFlags & 1) ani->startAnim(cmd->_messageNum, 0, flags); else ani->startAnim(cmd->_messageNum, cmd->_parId, flags); break; } case 8: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->startAnimEx(cmd->_messageNum, cmd->_parId, -1, -1); break; case 20: { if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; int flags = cmd->_field_14; if (flags <= 0) flags = -1; ExCommand2 *cmd2 = (ExCommand2 *)cmd; if (cmd->_excFlags & 1) { ani->startAnimSteps(cmd->_messageNum, 0, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } else { ani->startAnimSteps(cmd->_messageNum, cmd->_parId, cmd->_x, cmd->_y, cmd2->_points, cmd2->_pointsSize, flags); } break; } case 21: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->queueMessageQueue(0); ani->playIdle(); break; case 9: // Nop in original break; case 3: g_fp->_currentScene->_y = cmd->_messageNum - cmd->_messageNum % g_fp->_scrollSpeed; break; case 4: g_fp->_currentScene->_x = cmd->_messageNum - cmd->_messageNum % g_fp->_scrollSpeed; break; case 19: { if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; MessageQueue *mq = ani->getMessageQueue(); MessageQueue *mq2 = ani->changeStatics1(cmd->_messageNum); if (!mq2 || !mq2->getExCommandByIndex(0) || !mq) break; mq2->_parId = mq->_id; mq2->_flag1 = (cmd->_field_24 == 0); break; } case 22: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->_flags |= 4; ani->changeStatics2(cmd->_messageNum); break; case 6: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->hide(); break; case 27: if (!g_fp->_currentScene || g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param) == 0) { ani = g_fp->accessScene(cmd->_field_20)->getStaticANIObject1ById(cmd->_parentId, -1); if (ani) { ani = new StaticANIObject(ani); g_fp->_currentScene->addStaticANIObject(ani, 1); } } // fall through case 5: if (g_fp->_currentScene) ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; if (cmd->_field_14 >= 0) ani->_priority = cmd->_field_14; ani->show1(cmd->_x, cmd->_y, cmd->_messageNum, cmd->_parId); break; case 10: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; if (cmd->_field_14 >= 0) ani->_priority = cmd->_field_14; ani->show2(cmd->_x, cmd->_y, cmd->_messageNum, cmd->_parId); break; case 7: { if (!g_fp->_currentScene->_picObjList.size()) break; int offX = g_fp->_scrollSpeed * (cmd->_x / g_fp->_scrollSpeed); int offY = g_fp->_scrollSpeed * (cmd->_y / g_fp->_scrollSpeed); if (cmd->_messageNum) { g_fp->_currentScene->_x = offX - g_fp->_sceneRect.left; g_fp->_currentScene->_y = offY - g_fp->_sceneRect.top; if (cmd->_field_24) { g_fp->_currentScene->_messageQueueId = cmd->_parId; } } else { g_fp->_sceneRect.translate(offX - g_fp->_sceneRect.left, offY - g_fp->_sceneRect.top); g_fp->_currentScene->_x = 0; g_fp->_currentScene->_y = 0; g_fp->_currentScene->updateScrolling2(); } break; } case 34: if (!g_fp->_currentScene) break; ani = g_fp->_currentScene->getStaticANIObject1ById(cmd->_parentId, cmd->_param); if (!ani) break; ani->_flags = cmd->_messageNum | (ani->_flags & ~cmd->_field_14); break; case 35: global_messageHandler_handleSound(cmd); break; case 11: case 12: break; default: return 0; break; } return 1; }