aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorathrxx2011-08-06 00:40:53 +0200
committerJohannes Schickel2011-12-26 16:18:13 +0100
commitbac0caeb0ff712fe9002985c44c1ea651b86e018 (patch)
tree5fbfbe57957f441f07e7b644ba402fb21c5f1f40 /engines
parentaab9e62247af1c22772bb79821675fbab06c047d (diff)
downloadscummvm-rg350-bac0caeb0ff712fe9002985c44c1ea651b86e018.tar.gz
scummvm-rg350-bac0caeb0ff712fe9002985c44c1ea651b86e018.tar.bz2
scummvm-rg350-bac0caeb0ff712fe9002985c44c1ea651b86e018.zip
KYRA: (EOB) - lots of fixes towards EOB1 playability
also implement some new code (EOB1 portals, burning hands spell, etc.)
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/chargen.cpp6
-rw-r--r--engines/kyra/eob1.cpp34
-rw-r--r--engines/kyra/eob1.h2
-rw-r--r--engines/kyra/eob2.cpp4
-rw-r--r--engines/kyra/eobcommon.cpp89
-rw-r--r--engines/kyra/eobcommon.h12
-rw-r--r--engines/kyra/gui_eob.cpp4
-rw-r--r--engines/kyra/magic_eob.cpp32
-rw-r--r--engines/kyra/resource.h3
-rw-r--r--engines/kyra/saveload_eob.cpp6
-rw-r--r--engines/kyra/scene_eob.cpp32
-rw-r--r--engines/kyra/screen.cpp15
-rw-r--r--engines/kyra/screen.h5
-rw-r--r--engines/kyra/screen_eob.cpp11
-rw-r--r--engines/kyra/screen_eob.h4
-rw-r--r--engines/kyra/script_eob.cpp16
-rw-r--r--engines/kyra/sequences_eob1.cpp10
-rw-r--r--engines/kyra/sequences_eob2.cpp2
-rw-r--r--engines/kyra/sprites_eob.cpp19
-rw-r--r--engines/kyra/staticres_eob.cpp8
-rw-r--r--engines/kyra/timer_eob.cpp4
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;
}