diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/kyra/chargen.cpp | 6 | ||||
-rw-r--r-- | engines/kyra/eob1.cpp | 34 | ||||
-rw-r--r-- | engines/kyra/eob1.h | 2 | ||||
-rw-r--r-- | engines/kyra/eob2.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/eobcommon.cpp | 89 | ||||
-rw-r--r-- | engines/kyra/eobcommon.h | 12 | ||||
-rw-r--r-- | engines/kyra/gui_eob.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/magic_eob.cpp | 32 | ||||
-rw-r--r-- | engines/kyra/resource.h | 3 | ||||
-rw-r--r-- | engines/kyra/saveload_eob.cpp | 6 | ||||
-rw-r--r-- | engines/kyra/scene_eob.cpp | 32 | ||||
-rw-r--r-- | engines/kyra/screen.cpp | 15 | ||||
-rw-r--r-- | engines/kyra/screen.h | 5 | ||||
-rw-r--r-- | engines/kyra/screen_eob.cpp | 11 | ||||
-rw-r--r-- | engines/kyra/screen_eob.h | 4 | ||||
-rw-r--r-- | engines/kyra/script_eob.cpp | 16 | ||||
-rw-r--r-- | engines/kyra/sequences_eob1.cpp | 10 | ||||
-rw-r--r-- | engines/kyra/sequences_eob2.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/sprites_eob.cpp | 19 | ||||
-rw-r--r-- | engines/kyra/staticres_eob.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/timer_eob.cpp | 4 |
21 files changed, 254 insertions, 64 deletions
diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp index c8040ed9de..681412915d 100644 --- a/engines/kyra/chargen.cpp +++ b/engines/kyra/chargen.cpp @@ -236,7 +236,7 @@ bool CharacterGenerator::start(EobCharacter *characters, uint8 ***faceShapes) { } void CharacterGenerator::init() { - _screen->loadEobBitmap("CHARGENA", 3, 3); + _screen->loadShapeSetBitmap("CHARGENA", 3, 3); if (_faceShapes) { for (int i = 0; i < 44; i++) delete[] _faceShapes[i]; @@ -248,8 +248,8 @@ void CharacterGenerator::init() { _faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true); _screen->_curPage = 0; - _screen->loadEobCpsFileToPage("CHARGEN", 0, 3, 3, 0); - _screen->loadEobBitmap("CHARGENB", 3, 3); + _screen->loadEobBitmap("CHARGEN", 0, 3, 3, 0); + _screen->loadShapeSetBitmap("CHARGENB", 3, 3); if (_chargenMagicShapes) { for (int i = 0; i < 10; i++) delete[] _chargenMagicShapes[i]; diff --git a/engines/kyra/eob1.cpp b/engines/kyra/eob1.cpp index 95052311ff..762b2d1bd1 100644 --- a/engines/kyra/eob1.cpp +++ b/engines/kyra/eob1.cpp @@ -78,6 +78,9 @@ Common::Error EobEngine::init() { _scriptTimersCount = 1; + //_wllWallFlags[132] = 0x1f; + _wllWallFlags[133] = 1; + return Common::kNoError; } @@ -341,8 +344,25 @@ void EobEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int typ } } +void EobEngine::updateScriptTimersExtra() { + int cnt = 0; + for (int i = 1; i < 30; i++) { + if (_monsters[i].hitPointsCur <= 0) + cnt++; + } + + if (!cnt) { + for (int i = 1; i < 30; i++) { + if (getBlockDistance(_monsters[i].block, _currentBlock) > 3) { + killMonster(&_monsters[i], true); + break; + } + } + } +} + void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) { - _screen->loadEobBitmap("DOOR", 5, 3); + _screen->loadShapeSetBitmap("DOOR", 5, 3); _screen->_curPage = 2; if (doorType1 != 0xff) { @@ -351,8 +371,8 @@ void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s _doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2]; _doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); - _doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 << 1]; - _doorSwitches[shapeId1 + i].y = _doorSwitchCoords[(doorType1 << 1) + 1]; + _doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 * 6 + i * 2]; + _doorSwitches[shapeId1 + i].y = _doorSwitchCoords[doorType1 * 6 + i * 2 + 1]; } } @@ -362,8 +382,8 @@ void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s _doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2]; _doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); - _doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 << 1]; - _doorSwitches[shapeId2 + i].y = _doorSwitchCoords[(doorType2 << 1) + 1]; + _doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 * 6 + i * 2]; + _doorSwitches[shapeId2 + i].y = _doorSwitchCoords[doorType2 * 6 + i * 2+ 1]; } } @@ -383,7 +403,7 @@ void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wal case 4: case 5: case 6: - y = _dscDoorY2[mDim] - shp[1]; + y = _dscDoorY6[mDim] - shp[1]; d1 = _dscDoorCoordsExt[index << 1] >> 3; d2 = _dscDoorCoordsExt[(index << 1) + 1] >> 3; if (_shpDmX1 > d1) @@ -403,7 +423,7 @@ void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wal case 7: case 8: case 9: - y = _dscDoorY3[mDim] - _doorShapes[shapeIndex + 3][1]; + y = _dscDoorY7[mDim] - _doorShapes[shapeIndex + 3][1]; d1 = x - (_doorShapes[shapeIndex + 3][2] << 2); x -= (shp[2] << 2); drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5); diff --git a/engines/kyra/eob1.h b/engines/kyra/eob1.h index 8b805c00e8..21543ddfa5 100644 --- a/engines/kyra/eob1.h +++ b/engines/kyra/eob1.h @@ -81,6 +81,7 @@ private: // Monsters void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem); + void updateScriptTimersExtra(); // Level void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2); @@ -94,6 +95,7 @@ private: const uint8 *_dscDoorY4; const uint8 *_dscDoorY5; const uint8 *_dscDoorY6; + const uint8 *_dscDoorY7; const uint8 *_doorShapeEncodeDefs; const uint8 *_doorSwitchShapeEncodeDefs; diff --git a/engines/kyra/eob2.cpp b/engines/kyra/eob2.cpp index 2b4cf46afe..9efc558b7f 100644 --- a/engines/kyra/eob2.cpp +++ b/engines/kyra/eob2.cpp @@ -159,7 +159,7 @@ void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) { void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) { int cp = _screen->setCurPage(2); - _screen->loadEobBitmap(file, 3, 3); + _screen->loadShapeSetBitmap(file, 3, 3); uint8 tmpPal[16]; uint8 newPal[16]; @@ -291,7 +291,7 @@ bool DarkMoonEngine::killMonsterExtra(EobMonsterInPlay *m) { } const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) { - _screen->loadEobBitmap(filename, 3, 3); + _screen->loadShapeSetBitmap(filename, 3, 3); for (int i = 0; i < 3; i++) { _doorShapes[doorIndex * 3 + i] = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6)); shapeDefs += 8; diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index f323dd4e17..3e1001d2bd 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -98,6 +98,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _dscDoorScaleMult2 = 0; _dscDoorScaleMult3 = 0; _dscDoorY1 = 0; + _dscDoorXE = 0; _color9 = 17; _color10 = 23; @@ -137,6 +138,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _spellAnimBuffer = 0; _clericSpellOffset = 0; _restPartyElapsedTime = 0; + _allowSkip = false; _rrCount = 0; memset(_rrNames, 0, 10 * sizeof(const char*)); @@ -980,7 +982,7 @@ void EobCoreEngine::neutralizePoison(int character) { } void EobCoreEngine::npcSequence(int npcIndex) { - _screen->loadEobBitmap("OUTTAKE", 5, 3); + _screen->loadShapeSetBitmap("OUTTAKE", 5, 3); _screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK); drawNpcScene(npcIndex); @@ -1019,7 +1021,7 @@ void EobCoreEngine::initNpc(int npcIndex) { c->inventory[i] = duplicateItem(c->inventory[i]); } - _screen->loadEobBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); + _screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); _screen->_curPage = 2; c->faceShape = _screen->encodeShape(npcIndex << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); _screen->_curPage = 0; @@ -1257,7 +1259,7 @@ void EobCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i if (scumm_stricmp(_dialogueLastBitmap, file)) { if (!destRect) { if (!(flags & 1)) { - _screen->loadEobCpsFileToPage("BORDER", 0, 3, 3, 2); + _screen->loadEobBitmap("BORDER", 0, 3, 3, 2); _screen->copyRegion(0, 0, 0, 0, 184, 121, 2, page, Screen::CR_NO_P_CHECK); } else { _screen->copyRegion(0, 0, 0, 0, 184, 121, 0, page, Screen::CR_NO_P_CHECK); @@ -1267,7 +1269,7 @@ void EobCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i _screen->copyRegion(0, 0, 0, 0, 184, 121, 2, 6, Screen::CR_NO_P_CHECK); } - _screen->loadEobCpsFileToPage(file, 0, 3, 3, 2); + _screen->loadEobBitmap(file, 0, 3, 3, 2); strcpy(_dialogueLastBitmap, file); } @@ -1407,16 +1409,12 @@ bool EobCoreEngine::restParty_checkSpellsToLearn() { return false; } -void EobCoreEngine::restParty_npc() { - -} - bool EobCoreEngine::restParty_extraAbortCondition() { return false; } void EobCoreEngine::delay(uint32 millis, bool, bool) { - while (millis && !shouldQuit() && !skipFlag()) { + while (millis && !shouldQuit() && !(_allowSkip && skipFlag())) { updateInput(); uint32 step = MIN<uint32>(millis, (_tickLength / 5)); _system->delayMillis(step); @@ -1501,7 +1499,75 @@ int EobCoreEngine::countResurrectionCandidates() { } void EobCoreEngine::seq_portal() { - //_portalSeq + releaseDoorShapes(); + releaseMonsterShapes(0, 36); + releaseDecorations(); + + uint8 *shapes1[5]; + uint8 *shapes2[5]; + uint8 *shapes3[5]; + uint8 *shape0; + + _screen->loadShapeSetBitmap("PORTALA", 5, 3); + + for (int i = 0; i < 5; i++) { + shapes1[i] = _screen->encodeShape(i * 3, 0, 3, 75); + shapes2[i] = _screen->encodeShape(i * 3, 80, 3, 75); + shapes3[i] = _screen->encodeShape(15, i * 18, 15, 18); + } + + shape0 = _screen->encodeShape(30, 0, 8, 77); + _screen->loadEobBitmap("PORTALB", 0, 5, 3, 2); + + snd_playSoundEffect(33); + snd_playSoundEffect(19); + _screen->copyRegion(24, 0, 24, 0, 144, 104, 2, 5, Screen::CR_NO_P_CHECK); + _screen->copyRegion(24, 0, 24, 0, 144, 104, 0, 2, Screen::CR_NO_P_CHECK); + _screen->drawShape(2, shapes3[0], 28, 9, 0); + _screen->drawShape(2, shapes1[0], 34, 28, 0); + _screen->drawShape(2, shapes2[0], 120, 28, 0); + _screen->drawShape(2, shape0, 56, 27, 0); + _screen->crossFadeRegion(24, 0, 24, 0, 144, 104, 2, 0); + _screen->copyRegion(24, 0, 24, 0, 144, 104, 5, 2, Screen::CR_NO_P_CHECK); + delay(30 * _tickLength); + + for (const int8 *pos = _portalSeq; *pos > -1 && !shouldQuit(); ) { + int s = *pos++; + _screen->drawShape(0, shapes3[s], 28, 9, 0); + _screen->drawShape(0, shapes1[s], 34, 28, 0); + _screen->drawShape(0, shapes2[s], 120, 28, 0); + + if ((s == 1) && (pos >= _portalSeq + 3)) { + if (*(pos - 3) == 0) { + snd_playSoundEffect(24); + snd_playSoundEffect(86); + } + } + + s = *pos++; + if (s == 0) { + _screen->drawShape(0, shape0, 56, 27, 0); + } else { + s--; + _screen->copyRegion((s % 5) << 6, s / 5 * 77, 56, 27, 64, 77, 2, 0, Screen::CR_NO_P_CHECK); + if (s == 0) + snd_playSoundEffect(31); + else if (s == 3) { + if (*(pos - 2) == 3) + snd_playSoundEffect(90); + } + } + + _screen->updateScreen(); + delay(2 * _tickLength); + } + + delete[] shape0; + for (int i = 0; i < 5; i++) { + delete[] shapes1[i]; + delete[] shapes2[i]; + delete[] shapes3[i]; + } } bool EobCoreEngine::checkPassword() { @@ -1830,10 +1896,13 @@ bool EobCoreEngine::monsterAttackHitTest(EobMonsterInPlay *m, int charIndex) { int r = rollDice(1, 20); if (r != 20) { + // Prot from evil if (_characters[charIndex].effectFlags & 0x800) r -= 2; + // blur if (_characters[charIndex].effectFlags & 0x10) r -= 2; + // prayer if (_partyEffectFlags & 0x8000) r--; } diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index 7ebc883f3e..33b4a2fc2d 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -508,6 +508,7 @@ protected: void updateMonsters(int unit); void updateMonsterDest(EobMonsterInPlay *m); void updateMonsterDest2(EobMonsterInPlay *m); + void updateAllMonsterDests(); void turnFriendlyMonstersHostile(); int getNextMonsterDirection(int curBlock, int destBlock); int getNextMonsterPos(EobMonsterInPlay *m, int block); @@ -619,11 +620,12 @@ protected: const uint8 *_dscDoorScaleMult2; const uint8 *_dscDoorScaleMult3; const uint8 *_dscDoorY1; + const uint8 *_dscDoorXE; const uint8 *_wllFlagPreset; int _wllFlagPresetSize; const uint8 *_teleporterShapeCoords; - const uint8 *_portalSeq; + const int8 *_portalSeq; // Script void runLevelScript(int block, int flags); @@ -633,6 +635,7 @@ protected: const uint8 *initScriptTimers(const uint8 *pos); void updateScriptTimers(); + virtual void updateScriptTimersExtra() {} EobInfProcessor *_inf; int _stepCounter; @@ -803,7 +806,7 @@ protected: int restParty_getCharacterWithLowestHp(); bool restParty_checkHealSpells(int charIndex); bool restParty_checkSpellsToLearn(); - virtual void restParty_npc(); + virtual void restParty_npc() {} virtual bool restParty_extraAbortCondition(); // misc @@ -840,6 +843,8 @@ protected: const char *_rrNames[10]; int8 _rrId[10]; + bool _allowSkip; + Screen_Eob *_screen; GUI_Eob *_gui; @@ -881,6 +886,7 @@ protected: int _dstMonsterIndex; bool _preventMonsterFlash; int16 _foundMonstersArray[5]; + int8 _monsterBlockPosArray[6]; // magic void useMagicBookOrSymbol(int charIndex, int type); @@ -969,6 +975,7 @@ protected: void spellCallback_start_heal(); void spellCallback_start_layOnHands(); void spellCallback_start_turnUndead(); + bool spellCallback_end_kuotoaAttack(EobFlyingObject *fo); bool spellCallback_end_unk1Passive(EobFlyingObject *fo); bool spellCallback_end_unk2Passive(EobFlyingObject *fo); bool spellCallback_end_deathSpellPassive(EobFlyingObject *fo); @@ -1038,6 +1045,7 @@ protected: const uint8 *_magicFlightObjectProperties; const uint8 *_turnUndeadEffect; + const uint8 *_burningHandsDest; // Menu EobMenuDef *_menuDefs; diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index 9dec1584c5..04b863c325 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -150,7 +150,7 @@ Button *EobCoreEngine::gui_getButton(Button *buttonList, int index) { } void EobCoreEngine::gui_drawPlayField(bool refresh) { - _screen->loadEobCpsFileToPage("PLAYFLD", 0, 5, 3, 2); + _screen->loadEobBitmap("PLAYFLD", 0, 5, 3, 2); int cp = _screen->setCurPage(2); gui_drawCompass(true); @@ -163,7 +163,7 @@ void EobCoreEngine::gui_drawPlayField(bool refresh) { if (!_loading) _screen->updateScreen(); - _screen->loadEobCpsFileToPage("INVENT", 0, 5, 3, 2); + _screen->loadEobBitmap("INVENT", 0, 5, 3, 2); } void EobCoreEngine::gui_restorePlayField() { diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index 3eb7591413..12d2524545 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -142,7 +142,7 @@ void EobCoreEngine::usePotion(int charIndex, int weaponSlot) { } void EobCoreEngine::useWand(int charIndex, int weaponSlot) { - int v = _items[_characters[charIndex].inventory[weaponSlot]].value - 1; + int v = _items[_characters[charIndex].inventory[weaponSlot]].value; if (!v) { _txt->printMessage(_wandStrings[0]); return; @@ -535,7 +535,7 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d if (!fo->item && (_characters[c].effectFlags & 8)) { res = true; } else { - if ((_characters[c].flags & 1) && hitTest && !monsterAttackHitTest(&_monsters[0], c)) { + if ((_characters[c].flags & 1) && (!hitTest || monsterAttackHitTest(&_monsters[0], c))) { int dmg = rollDice(dcTimes, dcPips, dcOffs) * level; res = true; calcAndInflictCharacterDamage(c, 0, 0, dmg, dmgFlag, s, dmgType); @@ -638,7 +638,31 @@ void EobCoreEngine::spellCallback_start_armor() { } void EobCoreEngine::spellCallback_start_burningHands() { + static const int16 bX[] = { 0, 152, 24, 120, 56, 88 }; + static const int8 bY[] = { 64, 64, 56, 56, 56, 56 }; + for (int i = 0; i < 6; i++) + drawBlockObject(i & 1, 0, _firebeamShapes[(5 - i) >> 1], bX[i], bY[i], 0); + _screen->updateScreen(); + delay(2 * _tickLength); + + int cl = getCharacterMageLevel(_openBookChar); + int bl = calcNewBlockPosition(_currentBlock, _currentDirection); + + const int8 *pos = getMonsterBlockPositions(bl); + _preventMonsterFlash = true; + + int numDest = (_flags.gameID == GI_EOB1) ? 2 : 6; + const uint8 *d = &_burningHandsDest[_currentDirection * (_flags.gameID == GI_EOB1 ? 2 : 8)]; + + for (int i = 0; i < numDest; i++, d++) { + if (pos[*d] == -1) + continue; + calcAndInflictMonsterDamage(&_monsters[pos[*d]], 1, 3, cl << 1, 0x21, 4, 0); + } + + updateAllMonsterShapes(); + _sceneUpdateRequired = true; } void EobCoreEngine::spellCallback_start_detectMagic() { @@ -949,6 +973,10 @@ void EobCoreEngine::spellCallback_start_turnUndead() { _preventMonsterFlash = false; } +bool EobCoreEngine::spellCallback_end_kuotoaAttack(EobFlyingObject *fo) { + return magicObjectDamageHit(fo, 0, 0, 12, 1); +} + bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) { bool res = false; if (_partyEffectFlags & 0x20000) { diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 0f1539b610..f80fdd91c2 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -405,11 +405,13 @@ enum KyraResources { kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult6, kEobBaseDscDoorType5Offs, + kEobBaseDscDoorXE, kEobBaseDscDoorY1, kEobBaseDscDoorY3, kEobBaseDscDoorY4, kEobBaseDscDoorY5, kEobBaseDscDoorY6, + kEobBaseDscDoorY7, kEobBaseDscDoorCoordsExt, kEobBaseDscItemPosIndex, @@ -475,6 +477,7 @@ enum KyraResources { kEobBaseSpellProperties, kEobBaseMagicFlightProps, kEobBaseTurnUndeadEffect, + kEobBaseBurningHandsDest, kEob1MainMenuStrings, kEob1DoorShapeDefs, diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index 43a230e590..88f0c1c64e 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -205,7 +205,7 @@ Common::Error EobCoreEngine::loadGameState(int slot) { setupCharacterTimers(); - _screen->loadEobBitmap("CHARGENA", 3, 3); + _screen->loadShapeSetBitmap("CHARGENA", 3, 3); for (int i = 0; i < 6; i++) { EobCharacter *c = &_characters[i]; if (!c->flags || c->portrait < 0) @@ -213,12 +213,12 @@ Common::Error EobCoreEngine::loadGameState(int slot) { c->faceShape = _screen->encodeShape((c->portrait % 10) << 2, (c->portrait / 10) << 5, 4, 32, true); } - _screen->loadEobBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); + _screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); for (int i = 0; i < 6; i++) { EobCharacter *c = &_characters[i]; if (!c->flags || c->portrait >= 0) continue; - c->faceShape = _screen->encodeShape(-(c->portrait + 1), _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); + c->faceShape = _screen->encodeShape((-(c->portrait + 1)) << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); } _screen->_curPage = 0; diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index e6b3c26394..4c1bb1636f 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -690,7 +690,7 @@ void EobCoreEngine::loadLevel(int level, int sub) { } loadVcnData(gfxFile.c_str(), 0); - _screen->loadEobCpsFileToPage("INVENT", 0, 5, 3, 2); + _screen->loadEobBitmap("INVENT", 0, 5, 3, 2); enableSysTimer(2); _sceneDrawPage1 = 2; @@ -734,15 +734,13 @@ Common::String EobCoreEngine::initLevelData(int sub){ pos += 13; } - //////// _screen->loadPalette(tmpStr, _screen->getPalette(0)); - if (_flags.gameID == GI_EOB1) { pos += 11; _screen->setShapeFadeMode(0, false); _screen->setShapeFadeMode(1, false); } - else - _screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0)); + + _screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0)); Palette backupPal(256); backupPal.copy(_screen->getPalette(0), 224, 32, 224); @@ -796,9 +794,8 @@ Common::String EobCoreEngine::initLevelData(int sub){ for (int i = 0; i < 2; i++) { if (_flags.gameID == GI_EOB1) { - if (*pos == 0xFF) - continue; - loadMonsterShapes((const char *)(pos + 1), i * 18, false, *pos * 18); + if (*pos != 0xFF) + loadMonsterShapes((const char *)(pos + 1), i * 18, false, *pos * 18); pos += 13; } else { if (*pos++ != 0xEC) @@ -880,7 +877,7 @@ void EobCoreEngine::loadBlockProperties(const char *mazFile) { } void EobCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) { - _screen->loadEobBitmap(cpsFile, 3, 3); + _screen->loadShapeSetBitmap(cpsFile, 3, 3); Common::SeekableReadStream *s = _res->createReadStream(decFile); _levelDecorationDataSize = s->readUint16LE(); @@ -1142,7 +1139,10 @@ void EobCoreEngine::drawDecorations(int index) { int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint16 direction) { uint16 b = calcNewBlockPosition(curBlock, direction); int w = _levelBlockProperties[b].walls[direction ^ 2]; + int f = _wllWallFlags[w]; + if (!f) + assert (w < (_flags.gameID == GI_EOB1 ? 70 : 80)); if (w == 74 && _currentBlock == curBlock) { for (int i = 0; i < 5; i++) { @@ -1163,7 +1163,7 @@ void EobCoreEngine::notifyBlockNotPassable() { } void EobCoreEngine::moveParty(uint16 block) { - //processMonstersUnk1(); + updateAllMonsterDests(); uint16 old = _currentBlock; _currentBlock = block; @@ -1176,10 +1176,10 @@ void EobCoreEngine::moveParty(uint16 block) { runLevelScript(block, 1); - if (_levelBlockProperties[block].walls[0] == 26) + if (_flags.gameID == GI_EOB2 && _levelBlockProperties[block].walls[0] == 26) memset(_levelBlockProperties[block].walls, 0, 4); - //processMonstersUnk1(); + updateAllMonsterDests(); _stepCounter++; //_keybControlUnk = -1; _sceneUpdateRequired = true; @@ -1192,6 +1192,14 @@ int EobCoreEngine::clickedDoorSwitch(uint16 block, uint16 direction) { SpriteDecoration *d = &_doorSwitches[((v > 12 && v < 23) || v == 31) ? 3 : 0]; int x1 = d->x + _dscShapeCoords[138] - 4; int y1 = d->y - 4; + + if (_flags.gameID == GI_EOB1 && _currentLevel >= 4 && _currentLevel <= 6) { + if (v >= 30) + x1 += 4; + else + x1 += ((v - _dscDoorXE[v]) * 9); + } + if (!posWithinRect(_mouseX, _mouseY, x1, y1, x1 + (d->shp[2] << 3) + 8, y1 + d->shp[1] + 8) && (_clickedSpecialFlag == 0x40)) return clickedDoorNoPry(block, direction); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 5e424b4817..79edfe9d72 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -2971,6 +2971,9 @@ bool Screen::loadPalette(const char *filename, Palette &pal) { } else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) { numCols = stream->size() / Palette::kPC98BytesPerColor; pal.loadPC98Palette(*stream, 0, MIN(maxCols, numCols)); + } else if (_vm->gameFlags().gameID == GI_EOB1) { + numCols = stream->size() / Palette::kVGABytesPerColor; + pal.loadVGAPalette7bit(*stream, 0, MIN(maxCols, numCols)); } else { numCols = stream->size() / Palette::kVGABytesPerColor; pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols)); @@ -3438,6 +3441,18 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col stream.read(_palData + startIndex * 3, colors * 3); } +void Palette::loadVGAPalette7bit(Common::ReadStream &stream, int startIndex, int colors) { + assert(startIndex + colors <= _numColors); + + stream.read(_palData + startIndex * 3, colors * 3); + uint8 *pos = _palData + startIndex * 3; + for (int i = 0 ; i < colors; i++) { + *pos++ &= 0x3f; + *pos++ &= 0x3f; + *pos++ &= 0x3f; + } +} + void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) { assert(startIndex + colors <= _numColors); diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index cb7d73d1c1..d4f0dc97da 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -252,6 +252,11 @@ public: void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors); /** + * Load a VGA palette from the given stream masking out the upper bit. + */ + void loadVGAPalette7bit(Common::ReadStream &stream, int startIndex, int colors); + + /** * Load a AMIGA palette from the given stream. */ void loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors); diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index d3c2187177..ccbc2a166b 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -145,12 +145,15 @@ void Screen_Eob::printShadedText(const char *string, int x, int y, int col1, int printText(string, x, y, col1, 0); } -void Screen_Eob::loadEobBitmap(const char *file, int tempPage, int destPage) { - loadEobCpsFileToPage(file, 0, tempPage, destPage, -1); +void Screen_Eob::loadShapeSetBitmap(const char *file, int tempPage, int destPage) { + loadEobBitmap(file, 0, tempPage, destPage, -1); _curPage = 2; } -void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) { +void Screen_Eob::loadEobBitmap(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) { + //Common::String tmp = file; + //if (_vm->game() == GI_EOB1 && tmp.equalsIgnoreCase("spider")) + // tmp += "1"; Common::String tmp = Common::String::format("%s.CPS", file); Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp); bool loadAlternative = false; @@ -170,7 +173,7 @@ void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringDa tmp.setChar('X', 0); s = _vm->resource()->createReadStream(tmp); if (!s) - error("Screen_Eob::loadEobCpsFileToPage(): CPS file loading failed."); + error("Screen_Eob::loadEobBitmap(): CPS file loading failed."); s->seek(768); loadFileDataToPage(s, destPage, 64000); delete s; diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h index 19cbdb5b4a..909a561462 100644 --- a/engines/kyra/screen_eob.h +++ b/engines/kyra/screen_eob.h @@ -51,8 +51,8 @@ public: void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size); void printShadedText(const char *string, int x, int y, int col1, int col2); - void loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage); - void loadEobBitmap(const char *file, int tempPage, int destPage); + void loadEobBitmap(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage); + void loadShapeSetBitmap(const char *file, int tempPage, int destPage); uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool flag = false); void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd = -1, int flags = 0, ...); diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp index 715970074a..2b86aa8d51 100644 --- a/engines/kyra/script_eob.cpp +++ b/engines/kyra/script_eob.cpp @@ -54,7 +54,7 @@ const uint8 *EobCoreEngine::initScriptTimers(const uint8 *pos) { while (((int16)READ_LE_UINT16(pos)) != -1) { _scriptTimers[_scriptTimersCount].func = READ_LE_UINT16(pos); pos += 2; - uint16 ticks = (int16)READ_LE_UINT16(pos) * 18; + uint16 ticks = READ_LE_UINT16(pos) * 18; _scriptTimers[_scriptTimersCount].ticks = ticks; pos += 2; _scriptTimers[_scriptTimersCount++].next = _system->getMillis() + ticks * _tickLength; @@ -64,20 +64,26 @@ const uint8 *EobCoreEngine::initScriptTimers(const uint8 *pos) { } void EobCoreEngine::updateScriptTimers() { - if ((_scriptTimersMode & 1) && _stepsUntilScriptCall && _stepCounter > _stepsUntilScriptCall) { + bool timerUpdate = false; + if ((_scriptTimersMode & 2) && _stepsUntilScriptCall && _stepCounter > _stepsUntilScriptCall) { _inf->run(0, 0x20); _stepCounter = 0; + timerUpdate = true; } - if (_scriptTimersMode & 2) { + if (_scriptTimersMode & 1) { for (int i = 0; i < _scriptTimersCount; i++) { if (_scriptTimers[i].next < _system->getMillis()) { _inf->run(_scriptTimers[i].func, _flags.gameID == GI_EOB1 ? 0x20 : 0x80); _scriptTimers[i].next = _system->getMillis() + _scriptTimers[i].ticks * _tickLength; _sceneUpdateRequired = true; + timerUpdate = true; } } } + + if (timerUpdate) + updateScriptTimersExtra(); } EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _vm(engine), _screen(screen), @@ -211,13 +217,13 @@ bool EobInfProcessor::preventRest() const { void EobInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in) { _preventRest = in.readByte(); for (int i = 0; i < 18; i++) - _flagTable[i] = in.readUint16BE(); + _flagTable[i] = in.readUint32BE(); } void EobInfProcessor::saveState(Common::OutSaveFile *out) { out->writeByte(_preventRest); for (int i = 0; i < 18; i++) - out->writeUint16BE(_flagTable[i]); + out->writeUint32BE(_flagTable[i]); } const char *EobInfProcessor::getString(uint16 index) { diff --git a/engines/kyra/sequences_eob1.cpp b/engines/kyra/sequences_eob1.cpp index dcfabfeddd..8f360c071d 100644 --- a/engines/kyra/sequences_eob1.cpp +++ b/engines/kyra/sequences_eob1.cpp @@ -43,7 +43,7 @@ int EobEngine::mainMenu() { switch (menuChoice) { case 0: _screen->loadPalette("EOBPAL.COL", _screen->getPalette(0)); - _screen->loadEobCpsFileToPage("INTRO", 0, 5, 3, 2); + _screen->loadEobBitmap("INTRO", 0, 5, 3, 2); _screen->setScreenPalette(_screen->getPalette(0)); _screen->_curPage = 2; of = _screen->setFont(Screen::FID_6_FNT); @@ -107,6 +107,7 @@ void EobEngine::seq_playOpeningCredits() { static const char *cmpList[] = { "WESTWOOD.CMP", "AND.CMP", "SSI.CMP", "PRESENT.CMP", "DAND.CMP" }; static const uint8 frameDelay[] = { 140, 50, 100, 50, 140 }; + _allowSkip = true; _screen->loadPalette("WESTWOOD.COL", _screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); @@ -125,14 +126,21 @@ void EobEngine::seq_playOpeningCredits() { } delay(50 * _tickLength); + _allowSkip = false; } void EobEngine::seq_playIntro() { + _allowSkip = true; //_sound->playTrack(2); + + _allowSkip = false; } void EobEngine::seq_playFinale() { + _allowSkip = true; + + _allowSkip = false; } } // End of namespace Kyra diff --git a/engines/kyra/sequences_eob2.cpp b/engines/kyra/sequences_eob2.cpp index 8ff5581b9d..bba5a7a220 100644 --- a/engines/kyra/sequences_eob2.cpp +++ b/engines/kyra/sequences_eob2.cpp @@ -941,6 +941,7 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine * _system->delayMillis(150); _vm->resetSkipFlag(true); + _vm->_allowSkip = true; } DarkmoonSequenceHelper::~DarkmoonSequenceHelper() { @@ -960,6 +961,7 @@ DarkmoonSequenceHelper::~DarkmoonSequenceHelper() { _system->delayMillis(150); _vm->resetSkipFlag(true); + _vm->_allowSkip = false; } void DarkmoonSequenceHelper::loadScene(int index, int pageNum) { diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 3447b6bc7f..802ba4e4c8 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -54,7 +54,11 @@ int LolEobBaseEngine::getBlockDistance(uint16 block1, uint16 block2) { namespace Kyra { void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) { - _screen->loadEobBitmap(filename, 3, 3); + Common::String s = _flags.gameID == GI_EOB1 && !scumm_stricmp(filename, "spider") ? "spider1" : filename; + if (GI_EOB1 && !scumm_stricmp(filename, "rust")) + s += "1"; + + _screen->loadShapeSetBitmap(s.c_str(), 3, 3); const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2]; for (int i = 0; i < 6; i++, enc += 4) @@ -275,14 +279,14 @@ void EobCoreEngine::updateAttackingMonsterFlags() { } const int8 *EobCoreEngine::getMonsterBlockPositions(uint16 block) { - static int8 pos[6]; - memset(pos, -1, sizeof(pos)); + memset(_monsterBlockPosArray, -1, sizeof(_monsterBlockPosArray)); for (int8 i = 0; i < 30; i++) { if (_monsters[i].block != block) continue; - pos[_monsters[i].pos] = i; + assert(_monsters[i].pos < sizeof(_monsterBlockPosArray)); + _monsterBlockPosArray[_monsters[i].pos] = i; } - return pos; + return _monsterBlockPosArray; } int EobCoreEngine::getClosestMonsterPos(int charIndex, int block) { @@ -770,6 +774,11 @@ void EobCoreEngine::updateMonsterDest2(EobMonsterInPlay *m) { m->dest = _currentBlock; } +void EobCoreEngine::updateAllMonsterDests() { + for (int i = 0; i < 30; i++) + updateMonsterDest(&_monsters[i]); +} + void EobCoreEngine::turnFriendlyMonstersHostile() { EobMonsterInPlay *m = 0; for (int i = 0; i < 30; i++) { diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 9b15d4aea8..f07cd1186f 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -448,7 +448,7 @@ void EobCoreEngine::initStaticResource() { _npcPreset = _staticres->loadEobNpcData(kEobBaseNpcPresets, temp); _teleporterShapeCoords = _staticres->loadRawData(kEobBaseDscTelptrShpCoords, temp); - _portalSeq = _staticres->loadRawData(kEobBasePortalSeqData, temp); + _portalSeq = (const int8*)_staticres->loadRawData(kEobBasePortalSeqData, temp); _mnDef = _staticres->loadRawData(kEobBaseManDef, temp); _mnWord = _staticres->loadStrings(kEobBaseManWord, _mnNumWord); _mnPrompt = _staticres->loadStrings(kEobBaseManPrompt, temp); @@ -493,6 +493,7 @@ void EobCoreEngine::initStaticResource() { _dscDoorScaleMult2 = _staticres->loadRawData(kEobBaseDscDoorScaleMult2, temp); _dscDoorScaleMult3 = _staticres->loadRawData(kEobBaseDscDoorScaleMult3, temp); _dscDoorY1 = _staticres->loadRawData(kEobBaseDscDoorY1, temp); + _dscDoorXE = _staticres->loadRawData(kEobBaseDscDoorXE, temp); _dscItemPosIndex= _staticres->loadRawData(kEobBaseDscItemPosIndex, temp); _dscItemShpX = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscItemShpX, temp); @@ -533,6 +534,7 @@ void EobCoreEngine::initStaticResource() { _sparkEffectOfY = _staticres->loadRawData(kEobBaseSparkOfY, temp); _magicFlightObjectProperties = _staticres->loadRawData(kEobBaseMagicFlightProps, temp); _turnUndeadEffect = _staticres->loadRawData(kEobBaseTurnUndeadEffect, temp); + _burningHandsDest = _staticres->loadRawData(kEobBaseBurningHandsDest, temp); // Hard code the following strings, since EOB I doesn't have them in the original. // EOB I doesn't have load and save menus, because there is only one single @@ -1002,7 +1004,8 @@ void EobCoreEngine::initSpells() { ec2(empty); ec(empty); ec2(empty); - ec(unk1Passive); + ec1(kuotoaAttack); + ec2(unk1Passive); ec2(empty); ec2(unk2Passive); ec(deathSpellPassive); @@ -1064,6 +1067,7 @@ void EobEngine::initStaticResource() { _dscDoorY4 = _staticres->loadRawData(kEobBaseDscDoorY4, temp); _dscDoorY5 = _staticres->loadRawData(kEobBaseDscDoorY5, temp); _dscDoorY6 = _staticres->loadRawData(kEobBaseDscDoorY6, temp); + _dscDoorY7 = _staticres->loadRawData(kEobBaseDscDoorY7, temp); _dscDoorCoordsExt = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscDoorCoordsExt, temp); _monsterDistAttType10 = _staticres->loadRawData(kEob1MonsterDistAttType10, temp); diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index 9e03bdebcf..ba4d6a2475 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -210,7 +210,7 @@ void EobCoreEngine::advanceTimers(uint32 millis) { setupCharacterTimers(); - if (_scriptTimersMode & 2) { + if (_scriptTimersMode & 1) { for (int i = 0; i < _scriptTimersCount; i++) { if (_scriptTimers[i].next > ct) { uint32 chrt = _scriptTimers[i].next - ct; @@ -371,7 +371,7 @@ void EobCoreEngine::timerUpdateTeleporters(int timerNum) { _teleporterPulse ^= 1; for (int i = 0; i < 18; i++) { uint8 w = _visibleBlocks[i]->walls[_sceneDrawVarDown]; - if (w == 44 || w == 74) { + if ((_flags.gameID == GI_EOB1 && w == 52) || (_flags.gameID == GI_EOB2 && (w == 44 || w == 74))) { _sceneUpdateRequired = true; return; } |