void RMTony::stop(CORO_PARAM) { CORO_BEGIN_CONTEXT; uint32 pid; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); if (_actionItem != NULL) { // Call MPAL to choose the direction _ctx->pid = mpalQueryDoAction(21, _actionItem->mpalCode(), 0); if (_ctx->pid == CORO_INVALID_PID_VALUE) CORO_INVOKE_0(RMCharacter::stop); else { _bNeedToStop = false; // If we make the OnWhichDirection, we don't need at least after the Stop(). _bMoving = false; CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->pid, CORO_INFINITE); // @@@ Put an assert after 10 seconds } } else { CORO_INVOKE_0(RMCharacter::stop); } if (!_bActionPending) return; _bActionPending = false; executeAction(_action, _actionItem->mpalCode(), _actionParm); _actionItem = NULL; CORO_END_CODE; }
void RMTony::endStatic(CORO_PARAM, CharacterTalkType nTalk) { CORO_BEGIN_CONTEXT; int bodyEndPat; int finalPat; int headEndPat; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->bodyEndPat = 0; _ctx->finalPat = 0; _ctx->headEndPat = 0; endStaticCalculate(nTalk, _ctx->bodyEndPat, _ctx->finalPat, _ctx->headEndPat); if (_ctx->headEndPat != 0) { setPattern(_ctx->headEndPat); CORO_INVOKE_0(waitForEndPattern); } else { // Play please _body.setPattern(_ctx->bodyEndPat); CORO_INVOKE_0(_body.waitForEndPattern); } setPattern(_ctx->finalPat); _body.setPattern(0); _bIsStaticTalk = false; CORO_END_CODE; }
void RMTony::startStatic(CORO_PARAM, CharacterTalkType nTalk) { CORO_BEGIN_CONTEXT; int headPat, headLoopPat; int bodyStartPat, bodyLoopPat; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->headPat = _ctx->headLoopPat = 0; _ctx->bodyStartPat = _ctx->bodyLoopPat = 0; startStaticCalculate(nTalk, _ctx->headPat, _ctx->headLoopPat, _ctx->bodyStartPat, _ctx->bodyLoopPat); // e vai con i pattern _bIsStaticTalk = true; setPattern(_ctx->headPat); _body.setPattern(_ctx->bodyStartPat); CORO_INVOKE_0(_body.waitForEndPattern); CORO_INVOKE_0(waitForEndPattern); if (_ctx->headLoopPat != -1) setPattern(_ctx->headLoopPat); _body.setPattern(_ctx->bodyLoopPat); CORO_END_CODE; }
void RMTony::startTalk(CORO_PARAM, CharacterTalkType nTalkType) { CORO_BEGIN_CONTEXT; int headStartPat, bodyStartPat; int headLoopPat, bodyLoopPat; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->headStartPat = _ctx->bodyStartPat = 0; _ctx->headLoopPat = _ctx->bodyLoopPat = 0; if (!startTalkCalculate(nTalkType, _ctx->headStartPat, _ctx->bodyStartPat, _ctx->headLoopPat, _ctx->bodyLoopPat)) return; // Perform the set pattern if (_ctx->headStartPat != 0 || _ctx->bodyStartPat != 0) { setPattern(_ctx->headStartPat); _body.setPattern(_ctx->bodyStartPat); if (_ctx->bodyStartPat != 0) CORO_INVOKE_0(_body.waitForEndPattern); if (_ctx->headStartPat != 0) CORO_INVOKE_0(waitForEndPattern); } setPattern(_ctx->headLoopPat); if (_ctx->bodyLoopPat) _body.setPattern(_ctx->bodyLoopPat); CORO_END_CODE; }
void RMDialogChoice::prepare(CORO_PARAM) { CORO_BEGIN_CONTEXT; int i; RMPoint ptPos; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); addPrim(new RMGfxPrimitive(&_dlgText, RMPoint(0, 0))); addPrim(new RMGfxPrimitive(&_dlgTextLine, RMPoint(0, 155))); addPrim(new RMGfxPrimitive(&_dlgTextLine, RMPoint(0, 155 + 83))); addPrim(new RMGfxPrimitive(&_dlgTextLine, RMPoint(0, 155 + 83 + 83))); addPrim(new RMGfxPrimitive(&_dlgTextLine, RMPoint(0, 155 + 83 + 83 + 83))); _ctx->ptPos.set(20, 90); for (_ctx->i = 0; _ctx->i < _numChoices; _ctx->i++) { addPrim(new RMGfxPrimitive(&_drawedStrings[_ctx->i], _ctx->ptPos)); _ptDrawStrings[_ctx->i] = _ctx->ptPos; _ctx->ptPos.offset(0, _drawedStrings[_ctx->i].getDimy() + 15); } CORO_INVOKE_0(drawOT); clearOT(); _ptDrawPos.set(0, 480 - _ctx->ptPos._y); CORO_END_CODE; }
void RMDialogChoice::setSelected(CORO_PARAM, int pos) { CORO_BEGIN_CONTEXT; RMGfxBox box; RMRect rc; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); if (pos == _curSelection) return; _ctx->box.setPriority(5); if (_curSelection != -1) { _ctx->box.setColor(0xCC, 0xCC, 0xFF); _ctx->rc.topLeft() = RMPoint(18, _ptDrawStrings[_curSelection]._y); _ctx->rc.bottomRight() = _ctx->rc.topLeft() + RMPoint(597, _drawedStrings[_curSelection].getDimy()); addPrim(new RMGfxPrimitive(&_ctx->box, _ctx->rc)); addPrim(new RMGfxPrimitive(&_drawedStrings[_curSelection], _ptDrawStrings[_curSelection])); CORO_INVOKE_0(drawOT); clearOT(); } if (pos != -1) { _ctx->box.setColor(100, 100, 100); _ctx->rc.topLeft() = RMPoint(18, _ptDrawStrings[pos]._y); _ctx->rc.bottomRight() = _ctx->rc.topLeft() + RMPoint(597, _drawedStrings[pos].getDimy()); addPrim(new RMGfxPrimitive(&_ctx->box, _ctx->rc)); addPrim(new RMGfxPrimitive(&_drawedStrings[pos], _ptDrawStrings[pos])); } CORO_INVOKE_0(drawOT); clearOT(); _curSelection = pos; CORO_END_CODE; }
void RMTony::stopNoAction(CORO_PARAM) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); if (_bAction) CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _hActionThread, CORO_INFINITE); _bActionPending = false; _actionItem = NULL; CORO_INVOKE_0(stop); CORO_END_CODE; }
void RMGfxEngine::openOptionScreen(CORO_PARAM, int type) { CORO_BEGIN_CONTEXT; bool bRes; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->bRes = false; if (type == 0) CORO_INVOKE_2(_opt.init, _bigBuf, _ctx->bRes); else if (type == 1) CORO_INVOKE_3(_opt.initLoadMenuOnly, _bigBuf, true, _ctx->bRes); else if (type == 2) CORO_INVOKE_2(_opt.initNoLoadSave, _bigBuf, _ctx->bRes); else if (type == 3) CORO_INVOKE_3(_opt.initLoadMenuOnly, _bigBuf, false, _ctx->bRes); else if (type == 4) CORO_INVOKE_3(_opt.initSaveMenuOnly, _bigBuf, false, _ctx->bRes); if (_ctx->bRes) { g_vm->pauseSound(true); disableInput(); _inv.endCombine(); _curActionObj = 0; _curAction = TA_GOTO; _point.setAction(_curAction); _point.setSpecialPointer(RMPointer::PTR_NONE); _point.setCustomPointer(NULL); enableMouse(); g_vm->grabThumbnail(); // Exists the IDLE to avoid premature death in loading _bMustEnterMenu = true; if (type == 1 || type == 2) { GLOBALS._bIdleExited = true; } else { CORO_INVOKE_0(_tony.stopNoAction); GLOBALS._bIdleExited = false; CoroScheduler.createProcess(exitAllIdles, &_nCurLoc, sizeof(int)); } } CORO_END_CODE; }
void RMDialogChoice::show(CORO_PARAM, RMGfxTargetBuffer *bigBuf) { CORO_BEGIN_CONTEXT; RMPoint destpt; int deltay; int starttime; int elaps; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); CORO_INVOKE_0(prepare); _bShow = false; if (!_nInList && bigBuf != NULL) bigBuf->addPrim(new RMGfxPrimitive(this)); if (0) { _bShow = true; } else { _ctx->starttime = g_vm->getTime(); _ctx->deltay = 480 - _ptDrawPos._y; _ctx->destpt = _ptDrawPos; _ptDrawPos.set(0, 480); if (!_nInList && bigBuf != NULL) bigBuf->addPrim(new RMGfxPrimitive(this)); _bShow = true; _ctx->elaps = 0; while (_ctx->elaps < 700) { CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE); _ctx->elaps = g_vm->getTime() - _ctx->starttime; _ptDrawPos._y = 480 - ((_ctx->deltay * 100) / 700 * _ctx->elaps) / 100; } _ptDrawPos._y = _ctx->destpt._y; } CORO_END_CODE; }
void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) { // PROBLEM: You should change the location in a separate process to do the OnEnter CORO_BEGIN_CONTEXT; Common::InSaveFile *f; byte *state, *statecmp; uint32 size, sizecmp; char buf[4]; RMPoint tp; int loc; int ver; int i; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->f = g_system->getSavefileManager()->openForLoading(fn); if (_ctx->f == NULL) return; _ctx->f->read(_ctx->buf, 4); if (_ctx->buf[0] != 'R' || _ctx->buf[1] != 'M' || _ctx->buf[2] != 'S') { delete _ctx->f; return; } _ctx->ver = _ctx->buf[3]; if (_ctx->ver == 0 || _ctx->ver > TONY_SAVEGAME_VERSION) { delete _ctx->f; return; } if (_ctx->ver >= 0x3) { // There is a thumbnail. If the version is between 5 and 7, it's compressed if ((_ctx->ver >= 0x5) && (_ctx->ver <= 0x7)) { _ctx->i = 0; _ctx->i = _ctx->f->readUint32LE(); _ctx->f->seek(_ctx->i); } else { if (_ctx->ver >= 8) // Skip thumbnail size _ctx->f->skip(4); _ctx->f->seek(160 * 120 * 2, SEEK_CUR); } } if (_ctx->ver >= 0x5) { // Skip the difficulty level _ctx->f->seek(1, SEEK_CUR); } if (_ctx->ver >= 0x4) { // Skip the savegame name, which serves no purpose _ctx->i = _ctx->f->readByte(); _ctx->f->seek(_ctx->i, SEEK_CUR); } _ctx->loc = _ctx->f->readUint32LE(); _ctx->tp._x = _ctx->f->readUint32LE(); _ctx->tp._y = _ctx->f->readUint32LE(); _ctx->size = _ctx->f->readUint32LE(); if ((_ctx->ver >= 0x5) && (_ctx->ver <= 7)) { // MPAL was packed! _ctx->sizecmp = _ctx->f->readUint32LE(); _ctx->state = new byte[_ctx->size]; _ctx->statecmp = new byte[_ctx->sizecmp]; _ctx->f->read(_ctx->statecmp, _ctx->sizecmp); lzo1x_decompress(_ctx->statecmp, _ctx->sizecmp, _ctx->state, &_ctx->size); delete[] _ctx->statecmp; } else { // Read uncompressed MPAL data _ctx->state = new byte[_ctx->size]; _ctx->f->read(_ctx->state, _ctx->size); } mpalLoadState(_ctx->state); delete[] _ctx->state; // Inventory _ctx->size = _ctx->f->readUint32LE(); _ctx->state = new byte[_ctx->size]; _ctx->f->read(_ctx->state, _ctx->size); _inv.loadState(_ctx->state); delete[] _ctx->state; if (_ctx->ver >= 0x2) { // Version 2: box please _ctx->size = _ctx->f->readUint32LE(); _ctx->state = new byte[_ctx->size]; _ctx->f->read(_ctx->state, _ctx->size); g_vm->_theBoxes.loadState(_ctx->state); delete[] _ctx->state; } if (_ctx->ver >= 5) { // Version 5 bool bStat = false; bStat = _ctx->f->readByte(); _tony.setShepherdess(bStat); bStat = _ctx->f->readByte(); _inter.setPerorate(bStat); charsLoadAll(_ctx->f); } if (_ctx->ver >= 6) { // Load options GLOBALS._bCfgInvLocked = _ctx->f->readByte(); GLOBALS._bCfgInvNoScroll = _ctx->f->readByte(); GLOBALS._bCfgTimerizedText = _ctx->f->readByte(); GLOBALS._bCfgInvUp = _ctx->f->readByte(); GLOBALS._bCfgAnni30 = _ctx->f->readByte(); GLOBALS._bCfgAntiAlias = _ctx->f->readByte(); GLOBALS._bShowSubtitles = _ctx->f->readByte(); GLOBALS._bCfgTransparence = _ctx->f->readByte(); GLOBALS._bCfgInterTips = _ctx->f->readByte(); GLOBALS._bCfgDubbing = _ctx->f->readByte(); GLOBALS._bCfgMusic = _ctx->f->readByte(); GLOBALS._bCfgSFX = _ctx->f->readByte(); GLOBALS._nCfgTonySpeed = _ctx->f->readByte(); GLOBALS._nCfgTextSpeed = _ctx->f->readByte(); GLOBALS._nCfgDubbingVolume = _ctx->f->readByte(); GLOBALS._nCfgMusicVolume = _ctx->f->readByte(); GLOBALS._nCfgSFXVolume = _ctx->f->readByte(); // Load hotspots loadChangedHotspot(_ctx->f); } if (_ctx->ver >= 7) { loadMusic(_ctx->f); } delete _ctx->f; CORO_INVOKE_2(unloadLocation, false, NULL); loadLocation(_ctx->loc, _ctx->tp, RMPoint(-1, -1)); _tony.setPattern(RMTony::PAT_STANDRIGHT); // On older versions, need to an enter action if (_ctx->ver < 5) mpalQueryDoAction(0, _ctx->loc, 0); else { // In the new ones, we just reset the mcode mCharResetCodes(); } if (_ctx->ver >= 6) reapplyChangedHotspot(); CORO_INVOKE_0(restoreMusic); _bGUIInterface = true; _bGUIInventory = true; _bGUIOption = true; CORO_END_CODE; }
void RMGfxEngine::doFrame(CORO_PARAM, bool bDrawLocation) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); // Poll of input devices _input.poll(); if (_bMustEnterMenu && GLOBALS._bIdleExited) { _bOption = true; _bMustEnterMenu = false; GLOBALS._bIdleExited = false; } if (_bOption) { CORO_INVOKE_1(_opt.doFrame, &_input); _bOption = !_opt.isClosing(); if (!_bOption) { disableMouse(); enableInput(); mpalStartIdlePoll(_nCurLoc); g_vm->pauseSound(false); } } if (bDrawLocation && _bLocationLoaded) { // Location and objects _loc.doFrame(&_bigBuf); // Check the mouse input if (_bInput && !_tony.inAction()) { // If we are on the inventory, it is it who controls all input if (_inv.haveFocus(_input.mousePos()) && !_inter.active()) { // Left Click // ********** if (_input.mouseLeftClicked()/* && m_itemName.IsItemSelected()*/) { // Left click activates the combine, if we are on an object if (_inv.leftClick(_input.mousePos(), _curActionObj)) { _curAction = TA_COMBINE; _point.setAction(_curAction); } } else // Right Click // *********** if (_input.mouseRightClicked()) { if (_itemName.isItemSelected()) { _curActionObj = 0; _inv.rightClick(_input.mousePos()); } else _inv.rightClick(_input.mousePos()); } else // Right Release // ************* if (_input.mouseRightReleased()) { if (_inv.rightRelease(_input.mousePos(), _curAction)) { CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _curAction); _curAction = TA_GOTO; _point.setAction(_curAction); } } } else { // Options Menu // ************ if (_bGUIOption) { if (!_tony.inAction() && _bInput) { if ((_input.mouseLeftClicked() && _input.mousePos()._x < 3 && _input.mousePos()._y < 3)) { CORO_INVOKE_1(openOptionScreen, 0); goto SKIPCLICKSINISTRO; } else if (_input.getAsyncKeyState(Common::KEYCODE_ESCAPE)) CORO_INVOKE_1(openOptionScreen, 0); else if (!g_vm->getIsDemo()) { if (_input.getAsyncKeyState(Common::KEYCODE_F3) || _input.getAsyncKeyState(Common::KEYCODE_F5)) // Save game screen CORO_INVOKE_1(openOptionScreen, 4); else if (_input.getAsyncKeyState(Common::KEYCODE_F2) || _input.getAsyncKeyState(Common::KEYCODE_F7)) // Load game screen CORO_INVOKE_1(openOptionScreen, 3); } } } // Left Click // ************** if (_input.mouseLeftClicked() && !_inter.active()) { if (_curAction != TA_COMBINE) CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _point.curAction()); else if (_itemName.getSelectedItem() != NULL) CORO_INVOKE_4(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), TA_COMBINE, _curActionObj); if (_curAction == TA_COMBINE) { _inv.endCombine(); _point.setSpecialPointer(RMPointer::PTR_NONE); } _curAction = TA_GOTO; _point.setAction(_curAction); } SKIPCLICKSINISTRO: // Right Click // ************ if (_curAction == TA_COMBINE) { // During a combine, it cancels it if (_input.mouseRightClicked()) { _inv.endCombine(); _curActionObj = 0; _curAction = TA_GOTO; _point.setAction(_curAction); _point.setSpecialPointer(RMPointer::PTR_NONE); } } else if (_input.mouseRightClicked() && _itemName.isItemSelected() && _point.getSpecialPointer() == RMPointer::PTR_NONE) { if (_bGUIInterface) { // Before opening the interface, replaces GOTO _curAction = TA_GOTO; _curActionObj = 0; _point.setAction(_curAction); _inter.clicked(_input.mousePos()); } } // Right Release // ************* if (_input.mouseRightReleased()) { if (_bGUIInterface) { if (_inter.released(_input.mousePos(), _curAction)) { _point.setAction(_curAction); CORO_INVOKE_3(_tony.moveAndDoAction, _itemName.getHotspot(), _itemName.getSelectedItem(), _curAction); _curAction = TA_GOTO; _point.setAction(_curAction); } } } } // Update the name under the mouse pointer _itemName.setMouseCoord(_input.mousePos()); if (!_inter.active() && !_inv.miniActive()) CORO_INVOKE_4(_itemName.doFrame, _bigBuf, _loc, _point, _inv); } // Interface & Inventory _inter.doFrame(_bigBuf, _input.mousePos()); _inv.doFrame(_bigBuf, _point, _input.mousePos(), (!_tony.inAction() && !_inter.active() && _bGUIInventory)); } // Animate Tony CORO_INVOKE_2(_tony.doFrame, &_bigBuf, _nCurLoc); // Update screen scrolling to keep Tony in focus if (_tony.mustUpdateScrolling() && _bLocationLoaded) { RMPoint showThis = _tony.position(); showThis._y -= 60; _loc.updateScrolling(showThis); } if (_bLocationLoaded) _tony.setScrollPosition(_loc.scrollPosition()); if ((!_tony.inAction() && _bInput) || _bAlwaysDrawMouse) { _point.showCursor(); } else { _point.hideCursor(); } _point.doFrame(); // ********************** // Draw the list in the OT // ********************** CORO_INVOKE_0(_bigBuf.drawOT); #define FSTEP (480/32) // Wipe if (_bWiping) { switch (_nWipeType) { case 1: if (!(_rcWipeEllipse.bottom - _rcWipeEllipse.top >= FSTEP * 2)) { CoroScheduler.setEvent(_hWipeEvent); _nWipeType = 3; break; } _rcWipeEllipse.top += FSTEP; _rcWipeEllipse.left += FSTEP; _rcWipeEllipse.right -= FSTEP; _rcWipeEllipse.bottom -= FSTEP; break; case 2: if (!(_rcWipeEllipse.bottom - _rcWipeEllipse.top < 480 - FSTEP)) { CoroScheduler.setEvent(_hWipeEvent); _nWipeType = 3; break; } _rcWipeEllipse.top -= FSTEP; _rcWipeEllipse.left -= FSTEP; _rcWipeEllipse.right += FSTEP; _rcWipeEllipse.bottom += FSTEP; break; } } CORO_END_CODE; }
void RMTony::endTalk(CORO_PARAM) { CORO_BEGIN_CONTEXT; int headStandPat, headEndPat; int bodyEndPat, finalPat; bool bStatic; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); _ctx->headStandPat = _ctx->headEndPat = 0; _ctx->bodyEndPat = _ctx->finalPat = 0; _ctx->bStatic = false; _ctx->bodyEndPat = 0; _ctx->headEndPat = 0; if (!endTalkCalculate(_ctx->headStandPat, _ctx->headEndPat, _ctx->bodyEndPat, _ctx->finalPat, _ctx->bStatic)) return; // Handles the end of an animated and static, leaving everything unchanged if (_bIsStaticTalk) { if (_nTalkType == TALK_WITHBEARDSTATIC) { setPattern(0); if (_talkDirection == UP || _talkDirection == LEFT) { _body.setPattern(BPAT_WITHBEARDLEFT_STATIC); _nBodyOffset.set(-41, -14); } else if (_talkDirection == DOWN || _talkDirection == RIGHT) { _body.setPattern(BPAT_WITHBEARDRIGHT_STATIC); _nBodyOffset.set(-26, -14); } } else { setPattern(_ctx->headStandPat); CORO_INVOKE_0(_body.waitForEndPattern); } _bIsTalking = false; return; } // Set the pattern if (_ctx->headEndPat != 0 && _ctx->bodyEndPat != 0) { setPattern(_ctx->headEndPat); CORO_INVOKE_0(_body.waitForEndPattern); _body.setPattern(_ctx->bodyEndPat); CORO_INVOKE_0(waitForEndPattern); CORO_INVOKE_0(_body.waitForEndPattern); } else if (_ctx->bodyEndPat != 0) { setPattern(_ctx->headStandPat); CORO_INVOKE_0(_body.waitForEndPattern); _body.setPattern(_ctx->bodyEndPat); CORO_INVOKE_0(_body.waitForEndPattern); } else if (_ctx->headEndPat != 0) { CORO_INVOKE_0(_body.waitForEndPattern); setPattern(_ctx->headEndPat); CORO_INVOKE_0(waitForEndPattern); } else { CORO_INVOKE_0(_body.waitForEndPattern); } if (_ctx->finalPat != 0) { _body.setPattern(0); setPattern(_ctx->finalPat); } _bIsTalking = false; CORO_END_CODE; }