diff options
-rw-r--r-- | engines/kyra/lol.cpp | 59 | ||||
-rw-r--r-- | engines/kyra/lol.h | 9 | ||||
-rw-r--r-- | engines/kyra/screen_lol.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/screen_lol.h | 2 | ||||
-rw-r--r-- | engines/kyra/script_lol.cpp | 114 |
5 files changed, 167 insertions, 19 deletions
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 950dee57ae..3dd143fe4f 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -95,6 +95,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _currentControlMode = 0; _specialSceneFlag = 0; _lastCharInventory = -1; + _emcLastItem = -1; _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0; _levelShpList = _levelDatList = 0; @@ -1589,6 +1590,44 @@ void LoLEngine::fadeText() { _fadeText = false; } +void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage) { + uint16 *p1 = (uint16*) _tempBuffer5120; + uint16 *p2 = (uint16*) (_tempBuffer5120 + 640); + + for (int i = 0; i < w; i++) + p1[i] = i; + + for (int i = 0; i < h; i++) + p2[i] = i; + + for (int i = 0; i < w; i++) + SWAP(p1[_rnd.getRandomNumberRng(0, w - 1)], p1[i]); + + for (int i = 0; i < h; i++) + SWAP(p2[_rnd.getRandomNumberRng(0, h - 1)], p2[i]); + + for (int i = 0; i < h; i++) { + int i2 = i; + + for (int ii = 0; ii < w; ii++) { + int dx1 = x1 + p1[ii]; + int dy1 = y1 + p2[i2]; + int dx2 = x2 + p1[ii]; + int dy2 = y2 + p2[i2]; + + if (++i2 == h) + i2 = 0; + + _screen->setPagePixel(dstPage, dx2, dy2, _screen->getPagePixel(srcPage, dx1, dy1)); + } + + if (!dstPage && (i & 5) == 5) { + updateInput(); + _screen->updateScreen(); + } + } +} + void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifier) { generateBrightnessPalette(palette, _screen->getPalette(1), brightness, modifier); _screen->fadePalette(_screen->getPalette(1), 5, 0); @@ -3468,31 +3507,31 @@ void LoLEngine::drawMapPage(int pageNum) { uint8 w31 = _levelBlockProperties[b3].walls[1]; // draw block - _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 6, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 6, 0, _mapOverlay); // draw north wall drawMapBlockWall(b3, w31, sx, sy, 3); drawMapShape(w31, sx, sy, 3); if (_wllBuffer4[w31] & 0xc0) - _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay); // draw west wall drawMapBlockWall(b1, w13, sx, sy, 1); drawMapShape(w13, sx, sy, 1); if (_wllBuffer4[w13] & 0xc0) - _screen->copyBlockSpecial(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay); // draw east wall drawMapBlockWall(b0, w02, sx, sy, 0); drawMapShape(w02, sx, sy, 0); if (_wllBuffer4[w02] & 0xc0) - _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay); //draw south wall drawMapBlockWall(b2, w20, sx, sy, 2); drawMapShape(w20, sx, sy, 2); if (_wllBuffer4[w20] & 0xc0) - _screen->copyBlockSpecial(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay); } sx += 7; @@ -3545,7 +3584,7 @@ void LoLEngine::drawMapPage(int pageNum) { for (int ii = 0; ii < 11; ii++) { if (!_defaultLegendData[ii].enable) continue; - _screen->copyBlockSpecial(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay); _screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0); printMapText(_defaultLegendData[ii].stringId, 244, (tY << 3) + 22); tY++; @@ -3641,7 +3680,7 @@ void LoLEngine::redrawMapCursor() { int cx = _automapTopLeftX + (((_currentBlock - sx) % 32) * 7); int cy = _automapTopLeftY + (((_currentBlock - (sy << 5)) / 32) * 6); _screen->copyRegion(cx, cy, cx, cy, 16, 16, 2, 0); - _screen->copyBlockSpecial(2, 0, 0, 0, cx - 3, cy - 2, 16, 16, 0, _mapCursorOverlay); + _screen->copyBlockAndApplyOverlay(2, 0, 0, 0, cx - 3, cy - 2, 16, 16, 0, _mapCursorOverlay); _mapCursorOverlay[24] = _mapCursorOverlay[1]; for (int i = 1; i < 24; i++) @@ -3655,9 +3694,9 @@ void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int dir return; int cp = _screen->_curPage; - _screen->copyBlockSpecial(cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], _mapCoords[2][direction], _mapCoords[3][direction], 0, _mapOverlay); - _screen->copyBlockSpecial(cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay); - _screen->copyBlockSpecial(cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], _mapCoords[2][direction], _mapCoords[3][direction], 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay); + _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay); } void LoLEngine::drawMapShape(uint8 wall, int x, int y, int direction) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index c4d849ca6e..4a6ab6b0ab 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -585,6 +585,7 @@ private: int olol_allocItemPropertiesBuffer(EMCState *script); int olol_setItemProperty(EMCState *script); int olol_makeItem(EMCState *script); + int olol_placeMoveLevelItem(EMCState *script); int olol_createLevelItem(EMCState *script); int olol_getItemPara(EMCState *script); int olol_getCharacterStat(EMCState *script); @@ -671,6 +672,7 @@ private: int olol_calcInflictableDamagePerItem(EMCState *script); int olol_distanceAttack(EMCState *script); int olol_removeCharacterEffects(EMCState *script); + int olol_checkInventoryFull(EMCState *script); int olol_objectLeavesLevel(EMCState *script); int olol_addSpellToScroll(EMCState *script); int olol_playDialogueTalkText(EMCState *script); @@ -680,8 +682,11 @@ private: int olol_suspendMonster(EMCState *script); int olol_triggerEventOnMouseButtonRelease(EMCState *script); int olol_printWindowText(EMCState *script); + int olol_checkPartyForItemType(EMCState *script); int olol_setUnkDoorVar(EMCState *script); int olol_resetTimDialogueState(EMCState *script); + int olol_getItemOnPos(EMCState *script); + int olol_removeLevelItem(EMCState *script); int olol_savePage5(EMCState *script); int olol_restorePage5(EMCState *script); int olol_initDialogueSequence(EMCState *script); @@ -690,6 +695,8 @@ private: int olol_prepareSpecialScene(EMCState *script); int olol_restoreAfterSpecialScene(EMCState *script); int olol_assignCustomSfx(EMCState *script); + int olol_transformRegion(EMCState *script); + int olol_calcCoordinatesAddDirectionOffset(EMCState *script); int olol_resetPortraitsAndDisableSysTimer(EMCState *script); int olol_enableSysTimer(EMCState *script); int olol_checkNeedSceneRestore(EMCState *script); @@ -759,6 +766,7 @@ private: void resetPortraitsAndDisableSysTimer(); void toggleSelectedCharacterFrame(bool mode); void fadeText(); + void transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage); void setPaletteBrightness(uint8 *palette, int brightness, int modifier); void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier); void generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags); @@ -1104,6 +1112,7 @@ private: int _specialSceneFlag; int _lastCharInventory; uint16 _charStatusFlags[3]; + int _emcLastItem; FlyingObject *_flyingObjects; diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 47d526f915..f8dfca5615 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -618,7 +618,7 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); } -void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) { +void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) { if (!w || !h || !ovl) return; diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 2f230d79a6..6de38ff78d 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -76,7 +76,7 @@ public: uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight); uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; } - void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl); + void copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl); void applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl); uint8 getShapePaletteSize(const uint8 *shp); diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 41dc2b8ef0..f1d5b6b3ab 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -275,6 +275,12 @@ int LoLEngine::olol_makeItem(EMCState *script) { return makeItem(stackPos(0), stackPos(1), stackPos(2)); } +int LoLEngine::olol_placeMoveLevelItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setItemProperty(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + placeMoveLevelItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3) & 0xff, stackPos(4) & 0xff, stackPos(5)); + return 1; +} + int LoLEngine::olol_createLevelItem(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setItemProperty(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); int item = makeItem(stackPos(0), stackPos(1), stackPos(2)); @@ -1443,6 +1449,15 @@ int LoLEngine::olol_removeCharacterEffects(EMCState *script) { return 1; } +int LoLEngine::olol_checkInventoryFull(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkInventoryFull(%p)", (const void *)script); + for (int i = 0; i < 48; i++) { + if (_inventory[i]) + return 0; + } + return 1; +} + int LoLEngine::olol_objectLeavesLevel(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_objectLeavesLevel(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int o = _levelBlockProperties[stackPos(0)].assignedObjects; @@ -1570,6 +1585,32 @@ int LoLEngine::olol_printWindowText(EMCState *script) { return 1; } +int LoLEngine::olol_checkPartyForItemType(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkPartyForItemType(%p) (%d, %d, %d))", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + int p = stackPos(1); + + if (!stackPos(2)) { + for (int i = 0; i < 48; i++) { + if (!_inventory[i] || _itemsInPlay[_inventory[i]].itemPropertyIndex != p) + continue; + return 1; + } + + if (_itemsInPlay[_itemInHand].itemPropertyIndex == p) + return 1; + } + + int last = (stackPos(0) == -1) ? 3 : stackPos(0); + int first = (stackPos(0) == -1) ? 0 : stackPos(0); + + for (int i = first; i <= last; i++) { + if (itemEquipped(i, p)) + return 1; + } + + return 0; +} + int LoLEngine::olol_setUnkDoorVar(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setUnkDoorVar(%p) (%d)", (const void *)script, stackPos(0)); _emcDoorState = stackPos(0); @@ -1582,6 +1623,51 @@ int LoLEngine::olol_resetTimDialogueState(EMCState *script) { return 1; } +int LoLEngine::olol_getItemOnPos(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getItemOnPos(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int pX = stackPos(1); + if (pX != -1) + pX &= 0xff; + + int pY = stackPos(2); + if (pY != -1) + pY &= 0xff; + + int o = (stackPos(3) || _emcLastItem == -1) ? stackPos(0) : _emcLastItem; + + _emcLastItem = _levelBlockProperties[o].assignedObjects; + + while (_emcLastItem) { + if (_emcLastItem & 0x8000) { + o = _emcLastItem & 0x7fff; + _emcLastItem = _levelBlockProperties[o].assignedObjects; + continue; + } + + if (pX != -1 && (_itemsInPlay[_emcLastItem].x & 0xff) != pX) { + o = _emcLastItem & 0x7fff; + _emcLastItem = _levelBlockProperties[o].assignedObjects; + continue; + } + + if (pY != -1 && (_itemsInPlay[_emcLastItem].y & 0xff) != pY) { + o = _emcLastItem & 0x7fff; + _emcLastItem = _levelBlockProperties[o].assignedObjects; + continue; + } + + return _emcLastItem; + } + + return 0; +} + +int LoLEngine::olol_removeLevelItem(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_removeLevelItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + removeLevelItem(stackPos(0), stackPos(1)); + return 1; +} + int LoLEngine::olol_savePage5(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_savePage5(%p)", (const void *)script); savePage5(); @@ -1640,6 +1726,20 @@ int LoLEngine::olol_assignCustomSfx(EMCState *script) { return 0; } +int LoLEngine::olol_transformRegion(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_transformRegion(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + transformRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + return 1; +} + +int LoLEngine::olol_calcCoordinatesAddDirectionOffset(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcCoordinatesAddDirectionOffset(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + uint16 x = stackPos(0); + uint16 y = stackPos(1); + calcCoordinatesAddDirectionOffset(x, y, stackPos(2)); + return stackPos(3) ? x : y; +} + int LoLEngine::olol_resetPortraitsAndDisableSysTimer(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetPortraitsAndDisableSysTimer(%p)", (const void *)script); resetPortraitsAndDisableSysTimer(); @@ -2041,7 +2141,7 @@ void LoLEngine::setupOpcodeTable() { Opcode(olol_makeItem); // 0x10 - OpcodeUnImpl(); + Opcode(olol_placeMoveLevelItem); Opcode(olol_createLevelItem); Opcode(olol_getItemPara); Opcode(olol_getCharacterStat); @@ -2191,7 +2291,7 @@ void LoLEngine::setupOpcodeTable() { Opcode(olol_removeCharacterEffects); // 0x74 - OpcodeUnImpl(); + Opcode(olol_checkInventoryFull); Opcode(olol_objectLeavesLevel); OpcodeUnImpl(); OpcodeUnImpl(); @@ -2216,13 +2316,13 @@ void LoLEngine::setupOpcodeTable() { // 0x84 OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_checkPartyForItemType); Opcode(olol_setUnkDoorVar); Opcode(olol_resetTimDialogueState); // 0x88 - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_getItemOnPos); + Opcode(olol_removeLevelItem); Opcode(olol_savePage5); Opcode(olol_restorePage5); @@ -2245,8 +2345,8 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); // 0x98 - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_transformRegion); + Opcode(olol_calcCoordinatesAddDirectionOffset); Opcode(olol_resetPortraitsAndDisableSysTimer); Opcode(olol_enableSysTimer); |